Region Separation (CF1034C)
Region Separation(CF1034C)
明确题意:
1.每次砍完之后,所有联通快的权值和相等。
2.每次一个边集的边同时断,可以断多次边集。
题解:
和学长馈赠7类似,是加强版。
首先可以想到计算出每个子树的权值和—— (以 为根)。
设切到最后每个联通块的权值和为 ,那么合法的 满足 。
记 ,合法的 就还要满足 。
证明:
实际上是满足 的节点个数。
这些节点要选择断开与父节点相连的边,如果我们没有断开 条边(考虑到根节点不用断,实际上断开了 条边),也就没有把这棵树分成 个部分,那不可能每个部分的权值和为 。
但是还有一个问题: 的范围达到了 ,开桶存完全是不现实的。
于是考虑转变一下 的定义。
新定义: 为满足最后剩下了 个联通块,要断开与祖先相连的边的点的个数。(可能说不太清楚,看式子吧,实际上是 ,代换了一下,这样桶存的范围变成了 )
既要满足:
合法条件是 。
计算 :
暴力枚举 、 复杂度为 。
发现:对于一颗权值和为 的子树来说,它如果能对 做贡献,要满足:
设 , , ,则 。
所以
发现:当 是, 才为整数,即对 有贡献,所以 。
得出结论:当 时, 会在 中做贡献。
这里的计算是枚举 的倍数,调和级数,复杂度 。
这只是第一步:判断那些状态合法,接下来还要计算方案数。
设 为最后剩下了 个联通块的方案数。
初始化: 。
考虑转移: (切一下成倍增加)。
注意: 需要特殊判一下。
最后这部分时间复杂度 。
Code moo~~
#include<bits/stdc++.h> using namespace std; #define int long long #define re register int #define pc_ putchar(' ') #define pc_n putchar('\n') #define Bessie signed const int CTR = 1e6 + 7, MOD = 1e9 + 7; int n; int a[CTR], fa[CTR], siz[CTR]; int cnt[CTR], f[CTR]; int ans; int gcd(int x, int y) { return !y ? x : gcd(y, x % y); } Bessie main() { n = read(); for(re i = 1; i <= n; ++i) a[i] = read(); for(re i = 2; i <= n; ++i) fa[i] = read(); for(re i = n; i; --i) { siz[i] += a[i]; siz[fa[i]] += siz[i]; } for(re i = 1; i <= n; ++i) if(siz[1] / gcd(siz[1], siz[i]) <= n) ++cnt[siz[1] / gcd(siz[1], siz[i])]; for(re i = 1; i <= n; ++i) if(cnt[i]) for(re j = i; j <= n; j += i) f[j] += cnt[i]; for(re i = 1; i <= n; ++i) f[i] = (f[i] == i); for(re i = n; i > 1; --i) { if(f[i]) { for(re j = i + i; j <= n; j += i) (f[i] += f[j]) %= MOD; (ans += f[i]) %= MOD; } } ot(ans + 1),pc_n; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】