• 【AGC005 F】Many Easy Problems


    神他吗一天考一道码农题两道 FFT(其实还是我推式子一窍不通)

    题意

      给你一棵 (n) 个点的树,再给你一个常数 (k)
      设 (S) 为树上某些点的集合,定义 (f(S)) 为最小的包含 (S) 的连通子图的大小。
      (n) 个点选 (k) 个点一共有 ( binom{n}{k}) 种方案,请求出所有方案的 (f(S)) 之和。
      出题人觉得这样就太简单了,他决定让你求出 (k=1cdots n) 的答案。
      对于 (27\%) 的数据,(nle 2700)
      对于 (100\%) 的数据,$ nle 2 imes 10^5$

    题解

      这种题的关键点在于 (n^2) ( ext{dp})
      首先无法对于每个 (k) 快速求出答案,但我们可以考虑一个点对每个 (k) 的贡献。

      把 (x) 转为整棵树的根,则一个点 (x) 在这个连通子图内,当且仅当这 (k) 个点不都在 (x) 的某一个儿子子树里。

      那么贡献为 ( binom{n}{k}-sum binom{a_i}{k}),其中 (a_i) 为以 (x) 为根时,各个儿子子树的大小。
      不难发现,计算总的贡献时,( binom{n}{k}) 会被计算 (n) 次,每条边两端的子树大小都会被计算一次。
      设 (num_i) 表示大小为 (i) 的子树被计算的次数(不管加还是减),则 $$b_i = egin{cases} nspacespacespacespacespacespacespacespacespacespacespace (i=n) -num_ispace (i≠n) end{cases}$$
      其中 (cnt_i) 为大小为 (i) 的子树个数。
      由于一棵子树被且仅被被计算一次,所以 $$egin{align} ans_k&= sumlimits_{ige k} binom{i}{k} b_i onumber &= sumlimits_{ige k} frac{i!}{(i-k)!k!} b_i onumber &= frac{1}{k!} sumlimits_{ige k} b_i i! imes frac{1}{(i-k)!} onumber end{align}$$
      此时直接计算是 (O(n^2)) 的,可以得到 (27) 分。

      我们发现 (ans) 像一个可以卷积的生成函数。
      又发现 (sumlimits_{ige k} b_i i! imes frac{1}{(i-k)!} = [b_k k! frac{1}{0!}] + [b_{k+1} (k+1)! frac{1}{1!}] cdots + [b_n n! frac{1}{(n-k)!}])
      故我们需要构造一个序列 (c),使得 (c_{0cdots (n-k)}) 包含了 (b_k k!,space b_{k+1} (k+1)!,spacecdots ,space b_n n!);再构造一个序列 (d),使得 (d_{0cdots (n-k)}) 包含了 (frac{1}{0!},space frac{1}{1!},space cdots,space frac{1}{(n-k)!})。我们还要使一个序列的 (i) 由大变小,另一个序列的 (i) 由小变大,这样才卷积时才会把原序列中相同位置乘起来。
      于是不难构造出 $$egin{align} c_{n-i} &= b_i i! onumber d_i &= frac{1}{i!} onumber a_i &= sumlimits_{j+k=i} c_j d_k onumber ans_i &= frac{a_{n-i}}{i} onumber end{align}$$
      ( ext{NTT}) 计算出序列 (a) 即可。
      复杂度 (O(nlog n))

    #include<bits/stdc++.h>
    #define ll long long
    #define N 800010
    #define mod 924844033
    #define G 5
    #define invG 554906420
    using namespace std;
    inline int read(){
    	int x=0; bool f=1; char c=getchar();
    	for(;!isdigit(c); c=getchar()) if(c=='-') f=0;
    	for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
    	if(f) return x;
    	return 0-x;
    }
    int n;
    struct edge{int v,nxt;}e[N<<1];
    int hd[N],cnt;
    inline void add(int u, int v){e[++cnt]=(edge){v,hd[u]}, hd[u]=cnt;}
    int Pow(int x, int y){
    	int ret=1;
    	while(y){
    		if(y&1) ret=(ll)ret*x%mod;
    		x=(ll)x*x%mod;
    		y>>=1;
    	}
    	return ret;
    }
    int siz[N],num[N];
    void dfs(int u, int fa){
    	siz[u]=1;
    	for(int i=hd[u]; i; i=e[i].nxt) if(e[i].v!=fa){
    		dfs(e[i].v,u);
    		siz[u]+=siz[e[i].v];
    		--num[siz[e[i].v]], --num[n-siz[e[i].v]];
    	}
    }
    int jc[N],jcn[N];
    int a[N],b[N],c[N];
    struct Poly{
    	int n,bit,r[N];
    	void init(int x){
    		for(n=1, bit=0; n<=x; n<<=1, ++bit);
    		for(int i=1; i<n; ++i) r[i] = (r[i>>1]>>1) | ((i&1)<<(bit-1));
    	}
    	void dft(int *a, int f){
    		for(int i=0; i<n; ++i) if(i<r[i]) swap(a[i],a[r[i]]);
    		for(int i=1; i<n; i<<=1){
    			int wn = Pow(f==1 ? G : invG, (mod-1)/(i<<1));
    			for(int j=0; j<n; j+=(i<<1)){
    				int w=1, x, y;
    				for(int k=0; k<i; ++k, w=(ll)w*wn%mod)
    					x=a[j+k], y=(ll)w*a[j+i+k]%mod,
    					a[j+k]=(x+y)%mod, a[j+i+k]=(x-y+mod)%mod;
    			}
    		}
    		if(f==-1){
    			int tmp=Pow(n,mod-2);
    			for(int i=0; i<n; ++i) a[i]=(ll)a[i]*tmp%mod;
    		}
    	}
    }NTT;
    int main(){
    	n=read();
    	int u,v;
    	for(int i=1; i<n; ++i) u=read(), v=read(), add(u,v), add(v,u);
    	jc[0]=1;
    	for(int i=1; i<=n; ++i) jc[i]=(ll)jc[i-1]*i%mod;
    	jcn[n]=Pow(jc[n],mod-2);
    	for(int i=n-1; i>=0; --i) jcn[i]=(ll)jcn[i+1]*(i+1)%mod;
    	dfs(1,0);
    	num[n]=n;
    	for(int i=0; i<=n; ++i)
    		b[i]=((ll)num[n-i]*jc[n-i]%mod+mod)%mod,
    		c[i]=jcn[i];
    	NTT.init(n*2+1), NTT.dft(b,1), NTT.dft(c,1);
    	for(int i=0; i<NTT.n; ++i) a[i]=(ll)b[i]*c[i]%mod;
    	NTT.dft(a,-1);
    	for(int i=1; i<=n; ++i) printf("%lld
    ",(ll)a[n-i]*jcn[i]%mod);
    	return 0;
    }
    
  • 相关阅读:
    Adding and Deploying Solutions with PowerShell in SharePoint 2010
    List Schema
    sharepoint匿名实现的另一种方法
    SharePoint Tag Cloud
    Sharepoint Tags cloud
    Application Templates for Windows SharePoint Services 3.0
    asp.net弹出一个新页面时隐藏任务栏
    SQL提取数字,提取英文,提取中文,过滤重复字符方法
    TextBox中去掉边框、asp.net中实现行间距的代码
    asp.net中用LinkButton取到gridview中当前行的ID值
  • 原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/agc010f.html
Copyright © 2020-2023  润新知