[做题记录]做题记录 3

Jinan 2023 B

朴素 dp:fi,j 代表 i 为根的子树划分完,i 所在连通块大小为 j。转移平凡 O(nk)

考虑 k 很大时复杂度退化成 n2。发现 k 很大时连通块个数很小,只有 O(nk) 级别。因此不妨设 fi,a,b 表示 i 为根,子树中有 a 个大小为 k 的,b 个大小为 k+1 的,sziakb(k+1) 个节点在 i 所在连通块。发现状态总数实际上是 O(n×nk) 的。

k 进行阈值分治,不难发现当 k=n 是取得最有复杂度,即为 O(n1.5)

using namespace std;

const int N = 100010; 
const int mod = 998244353;
vector<int> E[N];
int f[N][1010], T, n, k, sz[N];
unordered_map<int, int> f2[N];
void dfs(int u, int fa) {
	sz[u] = 1; f[u][1] = 1;
	for (auto v : E[u]) if (v ^ fa) {
		dfs(v, u); vector<int> g(min(sz[u] + sz[v], k + 1) + 1);
		rep(i, 0, min(sz[u], k + 1))
			rep(j, 0, min(sz[v], k + 1 - i))
				g[i + j] = (g[i + j] + f[u][i] * f[v][j]) % mod;
		rep(i, 0, min(sz[u] + sz[v], k + 1)) f[u][i] = g[i];
		g.clear(); g.shrink_to_fit(); sz[u] += sz[v]; 
	} f[u][0] = (f[u][0] + f[u][k]) % mod;
	f[u][0] = (f[u][0] + f[u][k + 1]) % mod;
}
void dfs2(int u, int fa) {
	f2[u][1] = 1;
	for (auto v : E[u]) if (v ^ fa) {
		dfs2(v, u); unordered_map<int, int> g;
		for (auto [x1, y1] : f2[u]) for (auto [x2, y2] : f2[v]) if (x1 + x2 <= k + 1)
			(g[x1 + x2] += y1 * y2 % mod) %= mod; f2[u] = g;
	} if (f2[u].find(k) != f2[u].end()) (f2[u][0] += f2[u][k]) %= mod;
	if (f2[u].find(k + 1) != f2[u].end()) (f2[u][0] += f2[u][k + 1]) %= mod;
}
signed main() {
	scanf("%lld", &T);
	while (T -- ) {
		scanf("%lld%lld", &n, &k);
		rep(i, 1, n) E[i].clear();
		rop(i, 1, n) {
			int a, b; scanf("%lld%lld", &a, &b);
			E[a].push_back(b), E[b].push_back(a);
		} if (k <= (int)sqrt(n) * 3) {
			rep(i, 1, n) rep(j, 0, k + 1) f[i][j] = 0;
			dfs(1, 0); printf("%lld\n", f[1][0]);
		} else {
			rep(i, 1, n) f2[i].clear();
			dfs2(1, 0); printf("%lld\n", f2[1][0]);
		}
	} return 0;
} 

ECFinal 2023 C

第一眼看到这道题的想法:fi,j 表示 x 的前 i 个位置和为 j 的方案,以及 gi,j 表示 y 的前 i 个位置和为 j 的方案。这部分可以 O(n2w)

枚举 p,q。需要求出 imin(sp,sq)fp,i×fq,i。这是一个向量点积的形式。发现这个东西是 O(n3w) 的。使用多项式科技可以 O(n2wlog)

考虑更加高级的做法。不妨设 fi,j,k 表示 x 中做完了前 i 个,y 中做完了前 j 个,sbsa=k 的方案数。

k>0 则转移到 fi+1,j,否则转移到 fi,j+1。由于第三维大小是介于 ww 之间的,因此复杂度 O(n2w)

Nanjing 2023 D

一个简单的思路是:设 fi,j 表示以 i 为根,叶子节点到根节点路径上黑色节点个数均为 j 所需要修改的最少点数。这样可以做到 O(nm)。转移方程是:

fu,imin{cu,0+fv,i1,cu,1+fv,i}

这个东西可以长链剖分,然后对于轻链的合并做 (min,+) 卷积即可。可以做到线性。

posted @   Link-Cut-Y  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示