zoukankan      html  css  js  c++  java
  • 正睿2020三月集训day5

    正睿2020三月集训day5

    A.买到

    套路的状压dp

    一个小思维点是dp值可以同时作为时间的状态

    B. 口罩

    题意:删掉K条边再加上K条边,求不同的树的数量

    我们考虑二项式反演(钦定到恰好的转化),考虑钦定有(k)条边和原树不同(先断掉)

    然后对于(n-k+1=x)个连通块,其形成的不同的树的个数可以用prufer序列求出,即为(n^{x-2}prod a_i), 考虑通过长度为 (x-2) 的prufer序列,点对应联通块来构造树即可。

    (a_i) 是第 (i) 个连通块的点数,其实 (prod a_i) 相当于在每个连通块里选个点的方案数,可以树形dp连通块(n^2)求出(sumprod a_i)。最后反演求出恰好的再加起来就做完了。

    //#pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    inline char gc(){
        return getchar();
    }
    inline int read(){
    	int x=0,pos=1;char ch=gc();
    	for(;!isdigit(ch);ch=gc()) if(ch=='-') pos=0;
    	for(;isdigit(ch);ch=gc()) x=(x<<1)+(x<<3)+ch-'0';
    	return pos?x:-x; 
    } 
    #define ll long long
    #define FOR(i,a,b) for(register int i=a;i<=b;i++)
    #define ROF(i,a,b) for(register int i=a;i>=b;i--)
    const int mod = 1e9+7;
    const int N = 5021;
    int dp[N][N][2],sz[N];
    struct node{
    	int v,nex;
    }edge[N*2];
    int head[N],top=0;
    int f[N],g[N];
    void add(int u,int v){
    	edge[++top].v=v;
    	edge[top].nex=head[u];
    	head[u]=top;
    }
    int n,k;
    int ksm(int a,int b){
    	int res=1;
    	while(b){
    		if(b&1){
    			res=1ll*res*a%mod;
    		}a=1ll*a*a%mod;b>>=1;
    	}
    	return res;
    }
    void init(){
    	f[0]=1;
    	FOR(i,1,N-1) f[i]=1ll*f[i-1]*i%mod;
    	g[N-1]=ksm(f[N-1],mod-2);
    	ROF(i,N-2,0) g[i]=1ll*g[i+1]*(i+1)%mod;
    }
    int tmp[N][2];
    void dfs(int now,int pre){
    	sz[now]=1;
    	dp[now][1][0]=dp[now][1][1]=1;
    	for(int i=head[now];i;i=edge[i].nex){
    		int v=edge[i].v;
    		if(v==pre) continue;
    		dfs(v,now);
    		FOR(i,1,sz[now]+sz[v]) tmp[i][0]=tmp[i][1]=0;
    		FOR(i,1,sz[now]){
    			FOR(j,1,sz[v]){
    				tmp[i+j][0]=(tmp[i+j][0]+1ll*dp[now][i][0]*dp[v][j][1]%mod)%mod;
    				tmp[i+j][1]=(tmp[i+j][1]+1ll*dp[now][i][1]*dp[v][j][1]%mod)%mod;
    				tmp[i+j-1][0]=(tmp[i+j-1][0]+1ll*dp[now][i][0]*dp[v][j][0]%mod)%mod;
    				tmp[i+j-1][1]=(tmp[i+j-1][1]+1ll*dp[now][i][0]*dp[v][j][1]%mod+1ll*dp[now][i][1]*dp[v][j][0]%mod)%mod;
    			}
    		}
    		sz[now]+=sz[v];
    		FOR(i,1,sz[now]) dp[now][i][0]=tmp[i][0],dp[now][i][1]=tmp[i][1];
    	}
    }
    int res[N];
    ll C(ll a,ll b){
    	if(b>a||a<0||b<0) return 0;
    	return 1ll*f[a]*g[b]%mod*g[a-b]%mod;
    }
    int main(){
    	n=read(),k=read();
    	k=n-k-1;
    	init();
    	FOR(i,1,n-1){
    		int u=read(),v=read();add(u,v);add(v,u);
    	}
    	dfs(1,0);
    	ll tn=ksm(n,mod-2);
    	FOR(i,1,n){
    		res[i]=1ll*dp[1][i][1]*tn%mod;
    		tn=tn*n%mod;
    	}
    	int ans=0;
    	FOR(i,k,n){
    		ll w=0;
    		FOR(j,i,n){
    			if((j-i)&1) w=(w-1ll*C(j,i)*res[n-j]%mod+mod)%mod;
    			else w=(w+1ll*C(j,i)*res[n-j]%mod)%mod;
    		}
    		ans=(ans+w)%mod;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    C.了吗

    差分转化+对多项式系数是否为0的分析

    这个狗日的出题人超大常数(nlog n)开1e6,我谔谔

    这是TLE的代码:

    #pragma GCC diagnostic error "-std=c++11"
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-fstrict-overflow")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-skip-blocks")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("-fhoist-adjacent-loads")
    #pragma GCC optimize("-frerun-cse-after-loop")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("-funsafe-loop-optimizations")
    #pragma GCC optimize("inline-functions-called-once")
    #pragma GCC optimize("-fdelete-null-pointer-checks")
    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	int x=0,pos=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    	return pos?x:-x;
    } 
    const int N = 4e6+200;
    const int mod = 998244353;
    #define ll long long
    #define FOR(i,a,b) for(register int i=a;i<=b;++i)
    #define ROF(i,a,b) for(register int i=a;i>=b;--i)
    int n,k,s;
    int fa[N];
    struct node{
    	int v,nex;
    }edge[N*2];
    int head[N],top=0,w[N],b[N];
    void add(int u,int v){
    	edge[++top].v=v;
    	edge[top].nex=head[u];
    	head[u]=top;
    }
    void dfs(int now,int cnt){
    	cnt+=b[now];if(!b[now]) w[cnt]++;
    	for(int i=head[now];i;i=edge[i].nex){
    		int v=edge[i].v;
    		dfs(v,cnt);
    	}
    }
    int p[N*2],q[N*2],nlen,tmp[N*2],omg[N],inv[N];
    int f[N],g[N],r[N];
    int Lim,lim,li,tp;
    int ksm(int a,int b){
    	int res=1;
    	while(b){
    		if(b&1) res=1ll*a*res%mod;
    		a=1ll*a*a%mod;b>>=1;
    	}
    	return res;
    } 
    void init(){
    	f[0]=1;
    	FOR(i,1,1e6) f[i]=1ll*f[i-1]*i%mod;
    	g[1000000]=ksm(f[1000000],mod-2);
    	ROF(i,1e6-1,0) g[i]=1ll*g[i+1]*(i+1)%mod; 
    	omg[0]=inv[0]=1;
    	omg[1]=ksm(3,(mod-1)/Lim);inv[1]=ksm(omg[1],mod-2);
    	FOR(i,2,Lim){
    		omg[i]=1ll*omg[i-1]*omg[1]%mod;
    		inv[i]=1ll*inv[i-1]*inv[1]%mod;
    	}
    }
    int C(int a,int b){
    	if(b>a||a<0||b<0) return 0;
    	return 1ll*f[a]*g[b]%mod*g[a-b]%mod;
    }
    void getr(){
    	r[0]=0;
    	FOR(i,1,lim-1){
    		r[i]=(r[i>>1]>>1)+((i&1)?(1<<(li-1)):0);
    	}
    }
    void ntt(int *a,int opt){
    	FOR(i,0,lim-1) if(i<r[i]) swap(a[i],a[r[i]]);
    	for(int l=2;l<=lim;l<<=1){
    		int m=l/2;
    		for(int *g=a;g!=a+lim;g+=l){
    			for(int i=0;i<m;i++){
    				ll t;t=opt? 1ll*omg[Lim/l*i]*g[i+m]%mod : 1ll*inv[Lim/l*i]*g[i+m]%mod;
    				g[i+m]=(g[i]-t+mod)%mod;
    				g[i]=(g[i]+t)%mod;
    			}
    		}
    	}
    	if(opt==0){
    		int iv=ksm(lim,mod-2);
    		FOR(i,0,lim-1) a[i]=1ll*a[i]*iv%mod;
    	}
    }
    int FV[N*2];
    int nn;
    inline void getinv(const int *a,int *b,int n){
    	if(n==1) return b[0]=ksm(a[0],mod-2),void();
    	getinv(a,b,(n+1)/2);
    	lim=1,li=0;while(lim<n*2) lim*=2,li++;
    	FOR(i,(n+1)/2,lim-1) b[i]=0;
    	FOR(i,0,n-1) FV[i]=a[i];FOR(i,n,lim-1) FV[i]=0;
    	getr();
    	ntt(FV,1);ntt(b,1);
    	FOR(i,0,lim-1) b[i]=(2ll-1ll*FV[i]*b[i]%mod+mod)%mod*b[i]%mod;
    	if(n!=nn) ntt(b,0);
    }
    int main(){
    	n=read(),k=read(),s=read();
    	Lim=1;while(Lim<2*s+2) Lim*=2;
    	init();
    	FOR(i,2,n){
    		fa[i]=read();
    		add(fa[i],i); 
    	}
    	FOR(i,1,n) b[i]=read();
    	dfs(1,0); 
    	int flg=0;
    	ROF(i,20,0){
    		if(!w[i]) continue;
    		if((1<<i)>s) continue;
    		tp=0; 
    		for(int j=0;j*(1<<i)<=s;j++){
    			if((w[i]-j)&1) p[j]=(mod-C(w[i],j))%mod;
    			else p[j]=C(w[i],j); tp=j;
    		}  
    		
    		if(!flg){
    			nlen=tp;
    			FOR(j,0,nlen) q[j]=p[j];
    			flg=1;
    		}else{
    			FOR(j,0,nlen) tmp[j*2+1]=0,tmp[j*2]=q[j];
    			FOR(j,0,tp) q[j]=tmp[j];
    			lim=1;li=0; while(lim<2*tp+2) (lim<<=1),li++;
    			getr();
    			ntt(p,1);ntt(q,1);
    			FOR(j,0,lim-1) p[j]=1ll*q[j]*p[j]%mod;
    			ntt(p,0);
    			FOR(j,tp+1,lim-1) q[j]=p[j]=0;
    			FOR(j,0,tp) q[j]=p[j],p[j]=0; 
    			nlen=tp;
    		}
    	}
    	for(register int j=0;j*(k+1)<=tp;++j){
    		p[j*(k+1)]=q[j];
    	}
    	FOR(j,0,tp) tmp[j]=0;
    	nn=tp+1;
    	getinv(q,tmp,tp+1);
    	//FOR(j,tp+1,lim) p[j]=tmp[j]=0;
    	ntt(tmp,0)FOR(j,tp+1,lim) p[j]=0;ntt(p,1);
    	FOR(j,0,lim-1) tmp[j]=1ll*tmp[j]*p[j]%mod;
    	ntt(tmp,0);
    	ll an=0;
    	FOR(i,0,s){
    		an^=tmp[i];
    	}
    	printf("%lld
    ",an);
    	return 0;
    } 
    

    最后抄了个过的。

  • 相关阅读:
    Linux curl使用简单介绍
    SecureCRT编码转换vim
    BigTable/HBase基本概念解读 & Hbase shell常用命令
    Crontab用法说明(Linux)
    Sina SSO 登陆过程分析
    浅谈队列
    搞怪的 log4net 记录日志 性能测试
    iBatis.Net异步多线程 操作Ibatis报错
    高并发高负载的大型网站系统架构
    [置顶] IIs Web 站点安全 监控 站点自动部署 重启
  • 原文地址:https://www.cnblogs.com/lcyfrog/p/14252244.html
Copyright © 2011-2022 走看看