• 【agc005F】Many Easy Problems


    Portal --> agc005F

    Solution

    ​​  我们考虑统计每一个点的贡献,同样也是“正难则反”,(假设现在是一棵有根树,根节点是(1))发现一个点(x)对当前的选择方案没有贡献当且仅当选择的(k)个点都在(x)的某一个儿子的子树内或者都不在(x)的子树内,然后总的方案数也是很好统计的,所以我们可以考虑用减法求出一个点在选择(k)个点的情况下的贡献(val_k(x))

    ​​  

    [val_k(x)=inom n k-sumlimits_{uin son(x)}inom {size[u]} k ]

    ​​  其中(size[u])表示的是以(u)为根的子树大小

    ​​​  然后总的贡献就可以写成:

    [Ans(k)=sumlimits_{i=1}^{n}val(i)=ncdot inom n k-sumlimits_{i=1}^nsumlimits_{uin son(i)}inom {size[u]}k ]

    ​​  这个时候我们可以考虑将相同的(size[u])合并一下,记(cnt[x])表示(size=x)的节点个数:

    [Ans(k)=ncdotinom n k-sumlimits_{i=1}^{n}cnt[i]inom i k ]

    ​​​  前面的部分可以单独计算,我们将后面的sigma单独拎出来,将组合数展开:

    [egin{aligned} Ans1(k)&=sumlimits_{i=1}^n cnt[i]inom i k\ &=sumlimits_{i=1}^n cnt[i]cdot i!cdot k!cdot frac{1}{(i-k)!}\ Ans1(k)cdot k!&=sumlimits_{i=1}^n cnt[i]cdot i!cdot frac{1}{(i-k)!} end{aligned} ]

    ​​​  然后我们发现后面的那个其实是一个卷积形式,​​然后看一下这个长得很奇怪的模数:(924844033 =2^{21}*3^2*7^2+1),有个(2^{21})那所以我们可以放心NTT

    ​​​  令(A[i]=cnt[i]cdot i!),令(B[n-i]=frac{1}{(n-i)!})然后直接卷积一下即可,答案中指数为(n+k)的项的系数就是(Ans1(k))

    ​​​  然后就可以直接算了ovo

    ​ ​​  

    ​​​  代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int MOD=924844033,N=2*(1e5)+10,NT=N*4,G=5;
    struct xxx{
    	int y,nxt;
    }a[N*2];
    int h[N],fac[N],invfac[N],cnt[N],sz[N],ans[N];
    int vala[N],valb[N];
    int n,m,tot;
    int mul(int x,int y){return 1LL*x*y%MOD;}
    int add(int x,int y){return (1LL*x+y)%MOD;}
    int ksm(int x,int y){
    	int ret=1,base=x;
    	for (;y;y>>=1,base=mul(base,base))
    		if (y&1) ret=mul(ret,base);
    	return ret;
    }
    namespace NTT{/*{{{*/
    	int A[NT],B[NT],rev[NT],W[NT][2];
    	int len,invlen;
    	void init(){
    		int invg=ksm(G,MOD-2);
    		for (int i=1;i<=19;++i){
    			W[1<<i][0]=ksm(G,(MOD-1)/(1<<i));
    			W[1<<i][1]=ksm(invg,(MOD-1)/(1<<i));
    		}
    	}
    	void get_len(int n,int m){
    		for (int i=0;i<len;++i) A[i]=B[i]=0;
    		int bit=0;
    		for (len=1;len<=n+m;++bit,len<<=1);
    		rev[0]=0;
    		for (int i=1;i<len;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
    		invlen=ksm(len,MOD-2);
    	}
    	void ntt(int *a,int op){
    		int w,w_n,u,v;
    		for (int i=0;i<len;++i) if (rev[i]>i) swap(a[i],a[rev[i]]);
    		for (int step=2;step<=len;step<<=1){
    			w_n=W[step][op==-1];
    			for (int st=0;st<len;st+=step){
    				w=1;
    				for (int i=0;i<(step>>1);++i){
    					v=mul(a[st+i+(step>>1)],w);
    					u=a[st+i];
    					a[st+i]=add(u,v);
    					a[st+i+(step>>1)]=add(u,MOD-v);
    					w=mul(w,w_n);
    				}
    			}
    		}
    		if (op==1) return;
    		for (int i=0;i<len;++i) a[i]=mul(a[i],invlen);
    	}
    	void Ntt(int *a,int *b,int n,int m){
    		get_len(n,m);
    		for (int i=0;i<=n;++i) A[i]=a[i];
    		for (int i=0;i<=m;++i) B[i]=b[i];
    		ntt(A,1);
    		ntt(B,1);
    		for (int i=0;i<len;++i) A[i]=mul(A[i],B[i]);
    		ntt(A,-1);
    	}
    }/*}}}*/
    void Add(int x,int y){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;}
    void prework(int n){
    	NTT::init();
    	fac[0]=1;
    	for (int i=1;i<=n;++i) fac[i]=mul(fac[i-1],i);
    	invfac[n]=ksm(fac[n],MOD-2);
    	for (int i=n-1;i>=0;--i) invfac[i]=mul(invfac[i+1],i+1);
    }
    int C(int n,int m){return n<m?0:1LL*fac[n]*invfac[m]%MOD*invfac[n-m]%MOD;}
    void dfs(int fa,int x){
    	int u;
    	sz[x]=1;
    	for (int i=h[x];i!=-1;i=a[i].nxt){
    		u=a[i].y;
    		if (u==fa) continue;
    		dfs(x,u);
    		sz[x]+=sz[u];
    	}
    	if (fa) ++cnt[n-sz[x]],++cnt[sz[x]];
    }
    void solve(){
    	for (int i=1;i<=n;++i) vala[i]=mul(cnt[i],fac[i]);
    	for (int i=0;i<=n;++i) valb[n-i]=invfac[i];
    	//for (int i=0;i<=n;++i) printf("%d ",vala[i]);printf("
    ");
    	//for (int i=0;i<=n;++i) printf("%d ",valb[i]);printf("
    ");
    	NTT::Ntt(vala,valb,n+1,n+1);
    	for (int i=1;i<=n;++i) ans[i]=mul(NTT::A[n+i],invfac[i]);
    	for (int i=1;i<=n;++i)
    		printf("%d
    ",add(mul(n,C(n,i)),MOD-ans[i]));
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	int x,y;
    	scanf("%d",&n);
    	memset(h,-1,sizeof(h));
    	tot=0;
    	for (int i=1;i<n;++i){
    		scanf("%d%d",&x,&y);
    		Add(x,y); Add(y,x);
    	}
    	prework(n);
    	dfs(0,1);
    	solve();
    }
    
  • 相关阅读:
    Chandy-Lamport_algorithm
    3 differences between Savepoints and Checkpoints in Apache Flink
    列数 行数 表数 限制
    数据收集、传输、元数据管理、作业流调度、海量数据查询引擎、数据可视化
    分析云负载均衡产品
    端口被占用通过域名的处理 把www.domain.com均衡到本机不同的端口 反向代理 隐藏端口 Nginx做非80端口转发 搭建nginx反向代理用做内网域名转发 location 规则
    JSON Web Token
    查看开启端口的应用
    If the parts of an organization (e.g., teams, departments, or subdivisions) do not closely reflect the essential parts of the product, or if the relationship between organizations do not reflect the r
    微服务架构的理论基础
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9606789.html
Copyright © 2020-2023  润新知