zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    python网络爬虫与信息提取——5.信息组织与提取方法
    python网络爬虫与信息提取——4.Beautiful Soup库入门
    python网络爬虫与信息提取——3.requests爬虫实战
    python网络爬虫与信息提取——2.网络爬虫排除标准robots
    python网络爬虫与信息提取——1.requests库入门
    时间戳转日期
    splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目
    数组、对象等的按值传递与数字、字符串不同
    用flex做垂直居中
    手机端页面自适应解决方案-rem布局
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10201424.html
Copyright © 2011-2022 走看看