CF1554E You
题面
题解
注意a[u]是点u位置的a,不是每选一个点然后把非标记个数丢进vector里(
每选择一个点,相当于把相邻的非标记的边标为外向,最后一个点u的外向边个数就是a[u]
又观察发现每种边定向方案都可以构造(拓扑),所以一共有2^(n-1)种方案
设f[k]表示gcd=k,g[k]表示k|gcd,求出g之后反演一下
显然g[1]=2^(n-1);对于g[k>1],发现叶子必定内向,然后去掉叶子后的下一层唯一确定父亲边方向,如此类推得到方案唯一,因此可以O(n)判断一个g[k]是否存在
找到任意一个叶子的父亲,记为sp,则a[sp]必为son[sp]或son[sp]+1,即k|son[sp]或k|(son[sp]+1),因此check之前先判一下,这样要O(n)check的k就只有根号(其实是σ(n))个了
总复杂度\(O(n\sqrt n)\)
不用反演的话,gcd=k就先用k|gcd来求(唯一),最后求gcd判一下,多一个log
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (int a=b; a<=c; a++)
#define fd(a,b,c) for (int a=b; a>=c; a--)
#define add(a,b) a=((a)+(b))%mod
#define mod 998244353
#define ll long long
#define file
using namespace std;
const int N=1e5+10;
int a[N*2][2],ls[N],len;
int p[N],miu[N],lenp;
bool bz[N];
vector<int> v;
int son[N],sum[N],fa[N],sp;
ll f[N],g[N];
int T,n;
void init()
{
int l=100000;
miu[1]=1;
fo(i,2,l)
{
if (!bz[i])
p[++lenp]=i,miu[i]=-1;
fo(j,1,lenp)
if (1ll*i*p[j]<=l)
{
bz[i*p[j]]=1;
miu[i*p[j]]=-miu[i];
if (i%p[j]==0)
{
miu[i*p[j]]=0;
break;
}
}
else
break;
}
}
void New(int x,int y)
{
++len;
a[len][0]=y;
a[len][1]=ls[x];
ls[x]=len;
}
ll qpower(ll a,int b)
{
ll ans=1;
while (b)
{
if (b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void dfs(int Fa,int t)
{
int i;
fa[t]=Fa;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
{
++son[t];
dfs(t,a[i][0]);
}
v.push_back(t);
if (sp==0 && son[t]) sp=t;
}
int check(int k)
{
if (!(son[sp]%k==0 || (son[sp]+1)%k==0)) return 0;
memset(sum,0,(n+1)*4);
fo(i,0,n-2)
{
if (sum[v[i]]%k==0) ++sum[fa[v[i]]];
else
if ((sum[v[i]]+1)%k!=0) return 0;
}
if (sum[1]%k==0) return 1;
else return 0;
}
void solve()
{
scanf("%d",&n);
len=0;sp=0;
memset(ls,0,(n+1)*4);
memset(f,0,(n+1)*8);
memset(g,0,(n+1)*8);
memset(son,0,(n+1)*4);
memset(sum,0,(n+1)*4);
fo(i,1,n-1)
{
int x,y;
scanf("%d%d",&x,&y);
New(x,y),New(y,x);
}
if (n==2)
{
f[1]=2;
f[2]=0;
}
else
{
v.clear();
dfs(0,1);
g[1]=qpower(2,n-1);
fo(k,2,n) g[k]=check(k);
fo(i,1,n)
{
for (int j=i; j<=n; j+=i)
add(f[i],g[j]*miu[j/i]);
}
}
fo(i,1,n) printf("%lld ",f[i]);
printf("\n");
}
int main()
{
// freopen("CF1554E.in","r",stdin);
init();
scanf("%d",&T);
for (;T;--T) solve();
fclose(stdin);
fclose(stdout);
return 0;
}