【CF1554E】You
题目
题目链接:https://codeforces.com/contest/1554/problem/E
给定一棵 \(n\) 个点的树,你需要依次删去 \(n\) 个点,当点 \(i\) 被删除时,\(a_i\) 会被赋值为目前与 \(i\) 相连且没有被删除的点的数量。
对于 \(k=1\sim n\),分别求最后 \(\gcd(a_1,a_2,\cdots,a_n)=k\) 的方案数。两种方案不同当且仅当存在一个点被删的时间不同。多测。
\(t\leq 10^4,\sum n\leq 3\times 10^5\)。
思路
删点不好搞,时间倒流就变成了对于每一条边,可以把 \(1\) 的权值加到连接的两个点的其中一个,问最后所有点权值的 \(\gcd=k\) 的方案数。
那么显然总方案数为 \(2^{n-1}\) 次。而且要求 \(\gcd\) 恰好等于 \(k\),容易想到求出 \(\gcd\) 是 \(k\) 的倍数的方案数然后容斥一下。
记 \(f_i\) 表示最后所有点 \(\gcd\) 是 \(i\) 的倍数的方案数。首先显然有 \(f_1=2^{n-1}\)。
对于 \(i>1\),考虑如何构造出一个 \(\gcd\) 是 \(i\) 的倍数的解。
首先对于叶子节点,他们的权值一定是 \(0\)。对于一个非叶子节点 \(x\),假设我们已经递归求出了它的所有儿子的权值,那么 \(x\) 与它儿子之间的边的权值加到哪一边就已经确定了。能影响 \(x\) 权值的只剩 \(x\) 与父亲的边。
如果此时 \(x\) 的权值 \(v\) 是 \(k\) 的倍数,那么 \(v+1\) 一定不是 \(k\) 的倍数,那么这条边的权值就给 \(x\) 的父亲;否则如果 \(v+1\) 是 \(k\) 的倍数,权值就给 \(x\);否则无解。
通过这样构造我们发现对于 \(k>1\) 的部分,\(f_k\) 只可能是 \(0\) 或 \(1\)。所以对 \(k=2\sim n\) 都 dfs 一遍就可以做到单次 \(O(n^2)\) 了。
但是其中很多都是没有必要跑 dfs 的。观察到所有点的权值之和为 \(n-1\),那么所有点的 \(\gcd\) 也一定是 \(n-1\) 的因子。只需要把 \(n-1\) 的因子拿出来跑 dfs 即可。
时间复杂度 \(O(Qn(\log n+\sigma_0(n)))\)。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=100010,MOD=998244353;
int Q,n,tot,head[N],f[N];
vector<int> d[N];
struct edge
{
int next,to;
}e[N*2];
void add(int from,int to)
{
e[++tot]=(edge){head[from],to};
head[from]=tot;
}
int dfs(int x,int fa,int k)
{
int cnt=0;
for (int i=head[x];~i;i=e[i].next)
{
int v=e[i].to;
if (v!=fa)
{
int val=dfs(v,x,k);
if (val==-1) return -1;
cnt+=val;
}
}
if (cnt%k==0) return 1;
if (cnt%k==k-1) return 0;
return -1;
}
int main()
{
for (int i=2;i<N;i++)
for (int j=i;j<N;j+=i) d[j].push_back(i);
scanf("%d",&Q);
while (Q--)
{
memset(head,-1,sizeof(head));
memset(f,0,sizeof(f));
tot=0; f[1]=1;
scanf("%d",&n);
for (int i=1,x,y;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
f[1]=f[1]*2%MOD;
}
for (int i=0;i<d[n-1].size();i++)
if (dfs(1,0,d[n-1][i])==1) f[d[n-1][i]]=1;
for (int i=n;i>=1;i--)
for (int j=i*2;j<=n;j+=i) f[i]-=f[j];
for (int i=1;i<=n;i++) cout<<f[i]<<" ";
cout<<"\n";
}
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步