SMU Winter 2025 ptlks的周报Week 4 (2.17-2.22)

这周是蓝桥+天梯,粗心大意丢分有点多。

P10580

解法:

分解y/x的质因数次数,计算贡献

思路

赛时想出来了,但是不小心把自动取模板子里快速幂的数据类型搞错了,直接零蛋了。

代码

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ooo return
#define itn int
#define double long double
#define int long long
#define PII pair<int,int>
#define PIII pair<int,PII>
#define Endl '\n'
#define Ednl '\n'
#define endl '\n'
#define ednl '\n'
using namespace std;
const int N = 1e5 + 10, M = 32, SZ = (N) << 2, mod = 1e9 + 7;

using i64 = long long;

template<class T> constexpr T mypow(T n, i64 k) {
	T r = 1;
	for (; k; k /= 2, n *= n) {
		if (k % 2) {
			r *= n;
		}
	}
	return r;
}

template<int MOD> struct Zmod {
	int x;
	Zmod(signed x = 0) : x(norm(x % MOD)) {}
	Zmod(i64 x) : x(norm(x % MOD)) {}
	
	constexpr int norm(int x) const {
		if (x < 0) {
			x += MOD;
		}
		if (x >= MOD) {
			x -= MOD;
		}
		return x;
	}
	constexpr int val() const {
		return x;
	}
	constexpr Zmod operator-() const {
		Zmod val = norm(MOD - x);
		return val;
	}
	constexpr Zmod inv() const {
		assert(x != 0);
		return mypow(*this, MOD - 2);
	}
	friend constexpr auto &operator>>(istream &in, Zmod &j) {
		int v;
		in >> v;
		j = Zmod(v);
		return in;
	}
	friend constexpr auto &operator<<(ostream &o, const Zmod &j) {
		return o << j.val();
	}
	constexpr Zmod &operator++() {
		x = norm(x + 1);
		return *this;
	}
	constexpr Zmod &operator--() {
		x = norm(x - 1);
		return *this;
	}
	constexpr Zmod &operator+=(const Zmod &i) {
		x = norm(x + i.x);
		return *this;
	}
	constexpr Zmod &operator-=(const Zmod &i) {
		x = norm(x - i.x);
		return *this;
	}
	constexpr Zmod &operator*=(const Zmod &i) {
		x = i64(x) * i.x % MOD;
		return *this;
	}
	constexpr Zmod &operator/=(const Zmod &i) {
		return *this *= i.inv();
	}
	constexpr Zmod &operator%=(const int &i) {
		return x %= i, *this;
	}
	friend constexpr Zmod operator+(const Zmod i, const Zmod j) {
		return Zmod(i) += j;
	}
	friend constexpr Zmod operator-(const Zmod i, const Zmod j) {
		return Zmod(i) -= j;
	}
	friend constexpr Zmod operator*(const Zmod i, const Zmod j) {
		return Zmod(i) *= j;
	}
	friend constexpr Zmod operator/(const Zmod i, const Zmod j) {
		return Zmod(i) /= j;
	}
	friend constexpr Zmod operator%(const Zmod i, const int j) {
		return Zmod(i) %= j;
	}
	friend constexpr bool operator==(const Zmod i, const Zmod j) {
		return i.val() == j.val();
	}
	friend constexpr bool operator!=(const Zmod i, const Zmod j) {
		return i.val() != j.val();
	}
	friend constexpr bool operator<(const Zmod i, const Zmod j) {
		return i.val() < j.val();
	}
	friend constexpr bool operator>(const Zmod i, const Zmod j) {
		return i.val() > j.val();
	}
};

constexpr int MOD[] = {998244353, 1000000007};
using Z = Zmod<MOD[0]>;

Z power(int n) {
	return mypow(Z(2), n);
}


vector<int>g[N], gg[N];
int d[N];
Z fac[N], inv[N];
int a[N];


void fact(int n) {
	fac[0] = 1;
	for (int i = 1; i <= n; i++) {
		fac[i] = fac[i - 1] * i;
	}
	inv[n] = fac[n].inv();
	for (int i = n - 1; i >= 0; i--) {
		inv[i] = inv[i + 1] * (i + 1);
	}
}

Z C(int n, int m) {
	if (n < m)return 0;
	return fac[n] * inv[m] * inv[n - m];
}

int b[N];

void solve() {
	int x, y, n;
	cin >> x >> y >> n;
	if (y % x) {
		cout << 0 << endl;
		ooo;
	}
	int m = y / x;
	vector<PII> fact;
	for (int i = 2; i * i <= m; ++i) {
		int s=0;
		while (m % i == 0) {
			s++;
			m /= i;
		}
		if(s){
			fact.push_back({i,s});
		}
	}
	if (m > 1) fact.push_back({m,1});
	
	if (fact.size()==0) {
		cout << 1 << endl;
		ooo;
	}
	
	Z ans = 1;
	for (auto [x, y] : fact) {
		Z t1 = mypow(Z(y + 1), n);
		Z t2 = (2 * mypow(Z(y), n));
		Z t3 = mypow(Z(y - 1), n);
		Z tal = t1 - t2 + t3;
		ans *= tal;
	}
	cout << ans << endl;
}
int32_t main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int T = 1;
	cin >> T;
//	euler(1e4);
	while (T--) {
		solve();
	}
	return 0;
}

P8769

解法:

从第x天开始枚举到第一天,用最小堆维护最小值。

思路

由于天数越往后选择越少,所以可以直接从最后一天往后枚举,然后再根据天数加入更多合法选择,用堆维护即可。

代码

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ooo return
#define itn int
#define double long double
#define int long long
#define PII pair<int,int>
#define PIII pair<int,PII>
#define Endl '\n'
#define Ednl '\n'
#define endl '\n'
#define ednl '\n'
using namespace std;
const int N = 1e5 + 10, M = 32, SZ = (N) << 2, mod = 1e9 + 7;


vector<int>g[N], gg[N];
int d[N];
int a[N];


int b[N], c[N];

void solve() {
	int x, n;
	cin >> x >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i] >> b[i] >> c[i];
		if(b[i]<1e5)g[b[i]].push_back(i);
		else g[100000].push_back(i);
	}
	priority_queue<PII, vector<PII>, greater<PII>>q;
	for (int i = x; i <= 1e5; i++) {
		for (auto u : g[i]) {
			q.push({a[u], c[u]});
		}
	}
	int s = 0;
	for (int i = x; i >= 1; i--) {
		if (q.size() == 0) {
			cout << -1 << endl;
			return;
		}
		auto [u, y] = q.top();
		q.pop();
		y--;
		s += u;
		if (y) {
			q.push({u, y});
		}
		for (auto v : g[i - 1]) {
			q.push({a[v], c[v]});
		}
	}
	cout << s << endl;
}
int32_t main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int T = 1;
//	cin >> T;
//	euler(1e4);
	while (T--) {
		solve();
	}
	return 0;
}

P8810

解法:

枚举+dp

思路

数据范围很小,很容易想到dp,每个数都可以由前两个数转移过来。然后考虑如何去环,发现直接枚举其中两个数即可。此时复杂度为\(m^2 \cdot nm^3\)

代码

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ooo return
#define itn int
#define int long long
#define PII pair<int,int>
#define PIII pair<int,PII>
#define Endl '\n'
#define Ednl '\n'
#define endl '\n'
#define ednl '\n'
using namespace std;
const int N = 1e3 + 10, M = 32, SZ = (N) << 2, mod = 1e9 + 7;

using i64 = long long;

template<class T> constexpr T mypow(T n, i64 k) {
	T r = 1;
	for (; k; k /= 2, n *= n) {
		if (k % 2) {
			r *= n;
		}
	}
	return r;
}

template<int MOD> struct Zmod {
	int x;
	Zmod(signed x = 0) : x(norm(x % MOD)) {}
	Zmod(i64 x) : x(norm(x % MOD)) {}

	constexpr int norm(int x) const {
		if (x < 0) {
			x += MOD;
		}
		if (x >= MOD) {
			x -= MOD;
		}
		return x;
	}
	constexpr int val() const {
		return x;
	}
	constexpr Zmod operator-() const {
		Zmod val = norm(MOD - x);
		return val;
	}
	constexpr Zmod inv() const {
		assert(x != 0);
		return mypow(*this, MOD - 2);
	}
	friend constexpr auto &operator>>(istream &in, Zmod &j) {
		int v;
		in >> v;
		j = Zmod(v);
		return in;
	}
	friend constexpr auto &operator<<(ostream &o, const Zmod &j) {
		return o << j.val();
	}
	constexpr Zmod &operator++() {
		x = norm(x + 1);
		return *this;
	}
	constexpr Zmod &operator--() {
		x = norm(x - 1);
		return *this;
	}
	constexpr Zmod &operator+=(const Zmod &i) {
		x = norm(x + i.x);
		return *this;
	}
	constexpr Zmod &operator-=(const Zmod &i) {
		x = norm(x - i.x);
		return *this;
	}
	constexpr Zmod &operator*=(const Zmod &i) {
		x = i64(x) * i.x % MOD;
		return *this;
	}
	constexpr Zmod &operator/=(const Zmod &i) {
		return *this *= i.inv();
	}
	constexpr Zmod &operator%=(const int &i) {
		return x %= i, *this;
	}
	friend constexpr Zmod operator+(const Zmod i, const Zmod j) {
		return Zmod(i) += j;
	}
	friend constexpr Zmod operator-(const Zmod i, const Zmod j) {
		return Zmod(i) -= j;
	}
	friend constexpr Zmod operator*(const Zmod i, const Zmod j) {
		return Zmod(i) *= j;
	}
	friend constexpr Zmod operator/(const Zmod i, const Zmod j) {
		return Zmod(i) /= j;
	}
	friend constexpr Zmod operator%(const Zmod i, const int j) {
		return Zmod(i) %= j;
	}
	friend constexpr bool operator==(const Zmod i, const Zmod j) {
		return i.val() == j.val();
	}
	friend constexpr bool operator!=(const Zmod i, const Zmod j) {
		return i.val() != j.val();
	}
	friend constexpr bool operator<(const Zmod i, const Zmod j) {
		return i.val() < j.val();
	}
	friend constexpr bool operator>(const Zmod i, const Zmod j) {
		return i.val() > j.val();
	}
};

constexpr int MOD[] = {998244353, 1000000007};
using Z = Zmod<MOD[1]>;

Z power(int n) {
	return mypow(Z(2), n);
}

int max(int a,int b,int c){
	return max(a,max(b,c));
}

vector<PII>g[N];

int a[N], b[N], c[N];
Z dp[N][11][11];

void solve() {
	int n, m;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> b[i];
	}
	Z ans = 0;
	for (int l = 0; l <= 10; l++) {
		for (int r = 0; r <= 10; r++) {
			for (int i = 0; i < n; i++) {
				for (int j = 0; j <= 10; j++) {
					for (int k = 0; k <= 10; k++) {
						dp[i][j][k] = 0;
						if (i == 0) {
							if (j == l && k == r) {
								dp[i][j][k] = 1;
							}
						}
					}
				}
			}
			for (int t = 1; t <= n-2; t++) {
				for (int i = 0; i <= 10; i++) {
					for (int j = 0; j <= 10; j++) {
						for (int k = 0; k <= 10; k++) {
							if(max(i,j,k)==b[t-1]){
								dp[t][j][k]+=dp[t-1][i][j];
							}
						}
					}
				}
			}
			for (int i = 0; i <= 10; i++) {
				for (int j = 0; j <= 10; j++) {
					if(max(i,j,l)==b[n-2]&&
						max(j,l,r)==b[n-1]){
						ans+=dp[n-2][i][j];
					}
				}
			}
		}
	}
	cout<<ans<<endl;
}
int32_t main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int T = 1;
//	cin >> T;
//	euler(1e4);
	while (T--) {
		solve();
	}
	return 0;
}

P10418

解法:

树形dp

思路

维护当前子树内包含子树顶点的最长的1条边,2条边,3条边。树形dp越来越顺手了,但是赛时忘开longlong了......

代码

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ooo return
#define itn int
#define int long long
#define PII pair<int,int>
#define PIII pair<int,PII>
#define Endl '\n'
#define Ednl '\n'
#define endl '\n'
#define ednl '\n'
using namespace std;
const int N = 3e5 + 10, M = 32, SZ = (N) << 2,mod=1e9+7;



vector<PII>g[N];

int a[N],b[N];
itn dp[N][4];

void dfs(int x,int fa){
	int s1=0,s2=0,s3=0;
	int u1=0,u2=0,u3=0;
	int mx2=0,mi2=0,mm2=0,ii2=0;
	int mx3=0,mi3=0,mm3=0,ii3=0;
	for(auto[s,u]:g[x]){
		if(u!=fa){
			dfs(u,x);

			if(!s1){
				u1=u;
				s1=s;
			}else if(!s2){
				u2=u;
				s2=s;
			}else if(!s3){
				u3=u;
				s3=s;
			}
			if(s+dp[u][1]>mx2){
				mx2=s+dp[u][1];
				mi2=u;
			}else if(s+dp[u][1]>mm2){
				mm2=s+dp[u][1];
				ii2=u;
			}
			if(s+dp[u][2]>mx3){
				mx3=s+dp[u][2];
				mi3=u;
			}else if(s+dp[u][2]>mm3){
				mm3=s+dp[u][2];
				ii3=u;
			}
		}
	}
	dp[x][1]=s1;
	dp[x][2]=max(s1+s2,mx2);
	dp[x][3]=max(s1+s2+s3,mx3);
	if(u1!=mi2){
		dp[x][3]=max(s1+mx2,dp[x][3]);
	}else{
		dp[x][3]=max(s1+mm2,dp[x][3]);
		dp[x][3]=max(s2+mx2,dp[x][3]);
	}
}

void solve() {
	int n,m;
	cin>>n;
	for(int i=2;i<=n;i++){
		int x,y;
		cin>>x>>y;
		g[x].push_back({y,i});
		g[i].push_back({y,x});
	}
	for(int i=1;i<=n;i++){
		sort(g[i].begin(),g[i].end(),greater<>());
	}
	dfs(1,0);
	itn ans=0;
	for(int i=1;i<=n;i++){
//		cout<<i<<':'<<dp[i][1]<<" "<<dp[i][2]<<" "<<dp[i][3]<<"\n";
		ans=max(ans,dp[i][3]);
	}
	cout<<ans<<endl;
}
int32_t main() {
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int T = 1;
//	cin >> T;
//	euler(1e4);
	while (T--) {
		solve();
	}
	return 0;
}
posted @ 2025-02-23 19:36  ptlks  阅读(32)  评论(0)    收藏  举报