• 【题解】AT2064 Many Easy Problems(转换+NTT)


    【题解】AT2064 Many Easy Problems(转换+NTT)

    给定一棵树,请你回答(kin[1,n])(k)个点生成出来的虚树(steiner)的所有方案的大小的和。

    对于这种分元素然后每个元素对答案有一个相同的贡献的计数,一般都是考虑对于一个点考虑对于答案的贡献。对于一个确定的(k)和一个点(p),可以很轻易的算出(p)对于答案的贡献=({nchoose k }-( sum_{u in Son}{siz[u]choose k})-({n-siz[p]choose k}))。我们拿个同记录相同的组合数的上面的那个数,这个数组设为(s_i)那么设答案为(a_k),有((b_0=0))

    [a_k=sum_{i=0}^n b_i{ichoose k} ]

    拆开

    [a_k=sum_{i=0} {b_i i!over k! (i-k)!} ]

    随便化一下

    [k!a_k=sum_{i} {(b_ii!)over (i-k)!} ]

    按照上次的那种套路搞出来就能NTT了

    这一发TLE了,不知道为什么......

    upd: AtCoder 编译命令没有-DONLINE_JUDGE

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    
    using namespace std;  typedef long long ll;
    inline int qr(){
    	int ret=0,f=0,c=getchar();
    	while(!isdigit(c))f|=c==45,c=getchar();
    	while(isdigit(c)) ret=ret*10+c-48,c=getchar();
    	return f?-ret:ret;
    }
    const int maxn=1<<19|1;
    const int mod=924844033;
    typedef vector<int> poly;
    poly buk(maxn),c(maxn),ans;
    int inv[maxn],siz[maxn],r[maxn],jc[maxn],n;
    
    inline int MOD(const int&x){return x-mod>=0?x-mod:x;}
    inline int MOD(const int&x,const int&y){return 1ll*x*y%mod;}
    inline int MOD(const vector<int>&ve){int ret=1;for(const auto&t:ve) ret=MOD(ret,t); return ret;}
    
    inline int ksm(const int&ba,const int&p){
    	int ret=1;
    	for(int t=p,b=ba;t;t>>=1,b=MOD(b,b))
    		if(t&1) ret=MOD(ret,b);
    	return ret;
    }
    const int g=5;
    const int gi=ksm(5,mod-2);
    
    void pre(const int&n){
    	jc[0]=inv[0]=1;
    	for(int t=1;t<=n;++t) jc[t]=MOD(jc[t-1],t);
    	inv[n]=ksm(jc[n],mod-2);
    	for(int t=n-1;t;--t) inv[t]=MOD(inv[t+1],t+1);
    }
    
    void NTT(poly&a,const int&tag){
    	static int r[maxn];
    	int len=a.size();
    	for(int t=1;t<len;++t)
    		if((r[t]=r[t>>1]>>1|(t&1?len>>1:0))>t)
    			swap(a[t],a[r[t]]);
    	for(int t=1,wn,s=tag==1?g:gi;t<len;t<<=1){
    		wn=ksm(s,(mod-1)/(t<<1));
    		for(int i=0;i<len;i+=t<<1)
    			for(int j=0,w=1,p;j<t;++j,w=MOD(w,wn))
    				p=MOD(a[i+j+t],w),a[i+j+t]=MOD(a[i+j]-p+mod),a[i+j]=MOD(a[i+j]+p);
    	}
    	if(tag!=1)
    		for(int t=0,i=mod-(mod-1)/len;t<len;++t)
    			a[t]=MOD(a[t],i);
    }
    
    poly operator * (poly a,poly b){
    	int t1=a.size()+b.size()-1,len=1;
    	while(len<t1) len<<=1;
    	a.resize(len); b.resize(len);
    	NTT(a,1); NTT(b,1);
    	for(int t=0;t<len;++t) a[t]=MOD(a[t],b[t]);
    	NTT(a,-1); a.resize(t1);
    	return a;
    }
    
    poly e[maxn];
    void add(int fr,int to){
    	e[fr].push_back(to);
    	e[to].push_back(fr);
    }
    
    void dfs(int now,int last){
    	siz[now]=1;
    	for(auto t:e[now])
    		if(t^last)
    			dfs(t,now),++buk[siz[t]],siz[now]+=siz[t];
    	if(n-siz[now]>=0) ++buk[n-siz[now]];
    }
    
    int main(){
    	n=qr();
    	buk.resize(n+1);
    	c.resize(n+1);
    	for(int t=1;t<n;++t) add(qr(),qr());
    	dfs(1,0); pre(2e5);
    	for(int t=1;t<=n;++t) buk[t]=MOD(buk[t],jc[t]);
    	reverse(buk.begin(),buk.end());
    	for(int t=0;t<=n;++t) c[t]=inv[t];
    	ans=buk*c;
    	ans.resize(n+1);
    	reverse(ans.begin(),ans.end());
    	for(int t=1;t<=n;++t) printf("%d
    ",MOD(MOD(MOD(jc[n],inv[t]),MOD(inv[n-t],n))-MOD(ans[t],inv[t])+mod));
    	return 0;
    }
    
    
    
  • 相关阅读:
    如何在Elasticsearch中解析未分配的分片(unassigned shards)
    spark-streaming获取kafka数据的两种方式
    hbase读写优化
    手动修复 under-replicated blocks in HDFS
    kubectl常用命令(个人记录)
    mysql远程访问被拒绝问题
    海盗分金问题
    《转》基于OpenCV的傅里叶变换及逆变换
    char*,string和CString之间的转换
    commons-fileupload 核心API 分析
  • 原文地址:https://www.cnblogs.com/winlere/p/12181215.html
Copyright © 2020-2023  润新知