• loj#2540. 「PKUWC2018」随机算法


    传送门

    完了pkuwc咋全是dp怕是要爆零了……

    (f(S))表示(S)的排列数,(S)为不能再选的点集(也就是选到独立集里的点和与他们相邻的点),(mx(S))表示(S)状态下对应的独立集大小,枚举点(i),如果(i)不在(S)里,分情况考虑,设(w[i])表示点(i)以及与之相邻的点,(T=S|w[i])(sz[S])表示二进制(S)有多少个(1),如果(mx[T]=mx[S]+1),那么$$f[T]+=f[S] imes A_{n-sz[S]-1}^{sz[w[i]-(w[i]&S)]-1}$$
    上式的意思是,为了把(i)选进来,要把所有的与(i)相邻的点(除已经在(S)里的)都放到(i)的后面,那么共有(n-sz[S]-1)个位置,要放(sz[w[i]-(w[i]&S)]-1)个数,就是一个排列

    如果(mx[T]<mx[S]+1),那么先把(f[T])清零,然后按上面更新就是了

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int C=-1,Z=0;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    void print(R int x){
        if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    }
    const int N=(1<<20)+5,P=998244353;
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
    	R int res=1;
    	for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
    	return res;
    }
    int fac[25],inv[25],w[25],sz[N],dp[N],mx[N];
    int n,m,u,v,lim;
    inline int A(R int n,R int m){return mul(fac[n],inv[n-m]);}
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read(),m=read(),lim=(1<<n);
    	while(m--)u=read()-1,v=read()-1,w[u]|=(1<<v),w[v]|=(1<<u);
    	fp(i,0,n-1)w[i]|=(1<<i);
    	fp(i,1,lim-1)sz[i]=sz[i>>1]+(i&1);
    	fac[0]=inv[0]=fac[1]=inv[1]=1;
    	fp(i,2,n)fac[i]=mul(fac[i-1],i);
    	inv[n]=ksm(fac[n],P-2);
    	fd(i,n-1,2)inv[i]=mul(inv[i+1],i+1);
    	dp[0]=1;
    	fp(S,0,lim-1)if(dp[S]){
    		fp(i,0,n-1)if(!(S&(1<<i))){
    			int T=S|w[i];
    			if(mx[T]<mx[S]+1)mx[T]=mx[S]+1,dp[T]=0;
    			if(mx[T]==mx[S]+1)dp[T]=add(dp[T],mul(dp[S],A(n-sz[S]-1,sz[w[i]-(w[i]&S)]-1)));
    		}
    	}printf("%d
    ",mul(dp[lim-1],inv[n]));
    	return 0;
    }
    
  • 相关阅读:
    cmake常用工程示例大集合
    qt---cdb(Microsoft Console Debugger)调试
    Qt Creator设置多核编译(-j8参数)
    这都是些老观点了。世界在变,时代在变。中国人观念进步的更快
    微软全球执行副总裁沈向洋:三年内用人工智能赚100亿美元
    C# 6.0
    node.js + mongodb
    分布式消息系统kafka
    jQuery插件开发
    jqgrid-asp.net-mvc
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10201424.html
Copyright © 2020-2023  润新知