两道题比较像,放在一起写了,后者可以看成前者的加强版
(sto ztb orz)
先看AT那道题
考虑计算每个点的贡献,用容斥计算:每个点没有贡献当且仅当选的所有点都在以他为根时的一个子节点的子树里。所以对于每个点i,其贡献为$C_n^k-sum_{v∈son_i}C_{size[v]}^k$,这样我们就得到了一个$O(n^2)$的算法
考虑优化,来列出来总的式子
$ans=n*C_n^k-sumlimits_{i=1}^nsum_{v∈son_i}C_{size[v]}^k$
前面的随便算,先不管了。考虑后面,用卷积优化时常见的套路,开个桶$bkt[i]$统计size等于i的情况的个数
$ans'=sumlimits_{i=1}^n bkt[i] C_{i}^k$
组合数,拆除!
$ans'=sumlimits_{i=1}^n bkt[i]*i! frac{1}{k!(i-k)!}$
$k!*ans'=sumlimits_{i=1}^n bkt[i]*i! frac{1}{(i-k)!}$
上NTT即可
再来看ER那道题
我们仍然考虑贡献,点i产生贡献有两种方式:
1.作为被选出的点,有$C_{n-1}^{k-1}$种选的方法
2.作为构建虚树时被捉出来的LCA
显然重点在第二种上,我们仍然使用容斥来计算......
额式子太长了,不想写了,搬题解了
来啊,NTT啊(
Code:
Many Easy Problems↓
1 #include<cmath> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int N=1600005,mod=924844033; 8 int n,nm,t1,t2,cnt,G,Gi; 9 int p[N],noww[N],goal[N],siz[N]; 10 int rev[N],fac[N],inv[N],a[N],b[N],pw[30][2]; 11 void Read(int &x) 12 { 13 x=0; char ch=getchar(); 14 while(!isdigit(ch)) 15 ch=getchar(); 16 while(isdigit(ch)) 17 x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); 18 } 19 int Addit(int x,int y) 20 { 21 x+=y; 22 if(x>=mod) x-=mod; 23 return x; 24 } 25 int Qpow(int x,int k) 26 { 27 if(k==1) return x; 28 int tmp=Qpow(x,k/2); 29 return k%2?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod; 30 } 31 void Link(int f,int t) 32 { 33 noww[++cnt]=p[f]; 34 goal[cnt]=t,p[f]=cnt; 35 noww[++cnt]=p[t]; 36 goal[cnt]=f,p[t]=cnt; 37 } 38 int C(int a,int b) 39 { 40 return 1ll*fac[a]*inv[b]%mod*inv[a-b]%mod; 41 } 42 void DFS(int nde,int fth) 43 { 44 siz[nde]=1; 45 for(int i=p[nde];i;i=noww[i]) 46 if(goal[i]!=fth) 47 { 48 DFS(goal[i],nde); 49 a[siz[goal[i]]]++; 50 siz[nde]+=siz[goal[i]]; 51 } 52 a[n-siz[nde]]++; 53 } 54 void Pre() 55 { 56 fac[0]=inv[0]=1; 57 for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod; 58 inv[n]=Qpow(fac[n],mod-2); 59 for(int i=n-1;i;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod; 60 nm=2*n,n=1; while(n<=nm) n<<=1; G=5,Gi=Qpow(G,mod-2),nm>>=1; 61 for(int i=1;i<=n;i++) rev[i]=(rev[i>>1]>>1)+(i&1)*(n>>1); 62 for(int i=1;i<=24;i++) 63 { 64 pw[i][0]=Qpow(G,(mod-1)/(1<<i)); 65 pw[i][1]=Qpow(Gi,(mod-1)/(1<<i)); 66 } 67 for(int i=0;i<=nm;i++) a[i]=1ll*a[i]*fac[i]%mod,b[i]=inv[nm-i]; 68 } 69 void Trans(int *arr,int len,int typ) 70 { 71 register int i,j,k; 72 for(i=0;i<len;i++) 73 if(rev[i]>i) swap(arr[rev[i]],arr[i]); 74 for(i=2;i<=len;i<<=1) 75 { 76 int lth=i>>1,ort=pw[(int)log2(i)][typ==-1]; 77 for(j=0;j<len;j+=i) 78 { 79 int ori=1,tmp; 80 for(k=j;k<j+lth;k++,ori=1ll*ori*ort%mod) 81 { 82 tmp=1ll*ori*arr[k+lth]%mod; 83 arr[k+lth]=(arr[k]-tmp+mod)%mod; 84 arr[k]=(arr[k]+tmp)%mod; 85 } 86 } 87 } 88 if(typ==-1) 89 { 90 int Ni=Qpow(len,mod-2); 91 for(i=0;i<=len;i++) 92 arr[i]=1ll*arr[i]*Ni%mod; 93 } 94 } 95 int main() 96 { 97 Read(n); 98 for(int i=1;i<n;i++) 99 Read(t1),Read(t2),Link(t1,t2); 100 DFS(1,0),Pre(); 101 Trans(a,n,1),Trans(b,n,1); 102 for(int i=0;i<n;i++) a[i]=1ll*a[i]*b[i]%mod; 103 Trans(a,n,-1); 104 for(int i=1;i<=nm;i++) 105 { 106 int ans=1ll*C(nm,i)*nm%mod-1ll*a[nm+i]*inv[i]%mod; 107 printf("%d ",Addit(ans,mod)); 108 } 109 return 0; 110 }
两开花↓
1 #include<cmath> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int N=1600005,mod=998244353; 8 int n,m,nm,t1,t2,cnt,G,Gi; 9 int p[N],noww[N],goal[N],siz[N]; 10 int rev[N],fac[N],inv[N],a[N],b[N],pw[30][2]; 11 void Read(int &x) 12 { 13 x=0; char ch=getchar(); 14 while(!isdigit(ch)) 15 ch=getchar(); 16 while(isdigit(ch)) 17 x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); 18 } 19 int Addit(int x,int y) 20 { 21 x+=y; 22 if(x>=mod) x-=mod; 23 return x; 24 } 25 int Qpow(int x,int k) 26 { 27 if(k==1) return x; 28 int tmp=Qpow(x,k/2); 29 return k%2?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod; 30 } 31 void Link(int f,int t) 32 { 33 noww[++cnt]=p[f]; 34 goal[cnt]=t,p[f]=cnt; 35 noww[++cnt]=p[t]; 36 goal[cnt]=f,p[t]=cnt; 37 } 38 int C(int a,int b) 39 { 40 return 1ll*fac[a]*inv[b]%mod*inv[a-b]%mod; 41 } 42 void DFS(int nde,int fth) 43 { 44 siz[nde]=1; 45 for(int i=p[nde];i;i=noww[i]) 46 if(goal[i]!=fth) 47 { 48 DFS(goal[i],nde); 49 siz[nde]+=siz[goal[i]]; 50 } 51 a[n-1]++; int tmp=0; 52 for(int i=p[nde];i;tmp++,i=noww[i]) 53 if(goal[i]!=fth) a[n-siz[nde]+siz[goal[i]]]--; 54 a[n-siz[nde]]+=tmp-1-(nde!=1); 55 } 56 void Pre() 57 { 58 fac[0]=inv[0]=1; 59 for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod; 60 inv[n]=Qpow(fac[n],mod-2); 61 for(int i=n-1;i;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod; 62 nm=2*n,n=1; while(n<=nm) n<<=1; G=3,Gi=Qpow(G,mod-2),nm>>=1; 63 for(int i=1;i<=n;i++) rev[i]=(rev[i>>1]>>1)+(i&1)*(n>>1); 64 for(int i=1;i<=24;i++) 65 { 66 pw[i][0]=Qpow(G,(mod-1)/(1<<i)); 67 pw[i][1]=Qpow(Gi,(mod-1)/(1<<i)); 68 } 69 for(int i=0;i<=nm;i++) a[i]=1ll*Addit(a[i],mod)*fac[i]%mod,b[i]=inv[nm-i]; 70 } 71 void Trans(int *arr,int len,int typ) 72 { 73 register int i,j,k; 74 for(i=0;i<len;i++) 75 if(rev[i]>i) swap(arr[rev[i]],arr[i]); 76 for(i=2;i<=len;i<<=1) 77 { 78 int lth=i>>1,ort=pw[(int)log2(i)][typ==-1]; 79 for(j=0;j<len;j+=i) 80 { 81 int ori=1,tmp; 82 for(k=j;k<j+lth;k++,ori=1ll*ori*ort%mod) 83 { 84 tmp=1ll*ori*arr[k+lth]%mod; 85 arr[k+lth]=(arr[k]-tmp+mod)%mod; 86 arr[k]=(arr[k]+tmp)%mod; 87 } 88 } 89 } 90 if(typ==-1) 91 { 92 int Ni=Qpow(len,mod-2); 93 for(i=0;i<=len;i++) 94 arr[i]=1ll*arr[i]*Ni%mod; 95 } 96 } 97 int main() 98 { 99 Read(n),Read(m); 100 for(int i=1;i<n;i++) 101 Read(t1),Read(t2),Link(t1,t2); 102 DFS(1,0),Pre(); 103 Trans(a,n,1),Trans(b,n,1); 104 for(int i=0;i<n;i++) a[i]=1ll*a[i]*b[i]%mod; 105 Trans(a,n,-1); 106 for(int i=1;i<=m;i++) 107 { 108 int ans=Addit(1ll*a[nm+i]*inv[i]%mod,1ll*C(nm-1,i-1)*nm%mod); 109 printf("%lld ",1ll*ans*Qpow(C(nm,i),mod-2)%mod); 110 } 111 return 0; 112 }