zoukankan      html  css  js  c++  java
  • LOJ2540 随机算法

    题目链接
    看到(nleq 20),马上想到状压(dp).
    考虑用(f[S][i])表示集合(S)已经被考虑过了,独立集大小为(i)的方案数.
    显然,这个集合(S)的最外层显然都没有被选.
    考虑如何转移.
    枚举一个(j otin S),那么独立集大小显然(+1),然后所有和(j)相连的点都不能选了.
    那么用(w[j])记录与(j)相邻的集合,然后就可以转移了.
    (f[Scup j][i+1]leftarrow f[Scup j][i+1]+f[S][i]*A_{n-|S|-1}^{|w[j]|-|w[j]cap S|-1})
    时间复杂度看似是(O(2^n*n^2))的,但是因为跑不满,所以跑得过
    代码如下
    其实也没有什么好贴的了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #define N (22)
    #define P (998244353)
    #define inf (0x7f7f7f7f)
    #define rg register int
    #define Label puts("NAIVE")
    #define spa print(' ')
    #define ent print('
    ')
    #define rand() (((rand())<<(15))^(rand()))
    typedef long double ld;
    typedef long long LL;
    typedef unsigned long long ull;
    using namespace std;
    inline char read(){
    	static const int IN_LEN=1000000;
    	static char buf[IN_LEN],*s,*t;
    	return (s==t?t=(s=buf)+fread(buf,1,IN_LEN,stdin),(s==t?-1:*s++):*s++);
    }
    template<class T>
    inline void read(T &x){
    	static bool iosig;
    	static char c;
    	for(iosig=false,c=read();!isdigit(c);c=read()){
    		if(c=='-')iosig=true;
    		if(c==-1)return;
    	}
    	for(x=0;isdigit(c);c=read())x=((x+(x<<2))<<1)+(c^'0');
    	if(iosig)x=-x;
    }
    inline char readchar(){
    	static char c;
    	for(c=read();!isalpha(c);c=read())
    	if(c==-1)return 0;
    	return c;
    }
    const int OUT_LEN = 10000000;
    char obuf[OUT_LEN],*ooh=obuf;
    inline void print(char c) {
    	if(ooh==obuf+OUT_LEN)fwrite(obuf,1,OUT_LEN,stdout),ooh=obuf;
    	*ooh++=c;
    }
    template<class T>
    inline void print(T x){
    	static int buf[30],cnt;
    	if(x==0)print('0');
    	else{
    		if(x<0)print('-'),x=-x;
    		for(cnt=0;x;x/=10)buf[++cnt]=x%10+48;
    		while(cnt)print((char)buf[cnt--]);
    	}
    }
    inline void flush(){fwrite(obuf,1,ooh-obuf,stdout);}
    int n,s[N][N],w[N],Lim,cnt[(1<<N)],m;
    LL f[1<<N][N+1],jc[N],inv[N];
    int popcount(int x){
    	int cnt=0;
    	for(;x;x&=(x-1))cnt++;
    	return cnt;
    }
    LL ksm(LL a,int p){
    	LL res=1;
    	while(p){
    		if(p&1)res=(res*a)%P;
    		a=(a*a)%P,p>>=1;
    	}
    	return res;
    }
    LL A(int n,int m){
    	return jc[n]*inv[n-m]%P;
    }
    int main(){
    	read(n),read(m);
    	Lim=(1<<n)-1,jc[0]=inv[0]=1;
    	for(int i=1;i<=m;i++){
    		int x,y;
    		read(x),read(y);
    		s[x][y]=s[y][x]=1;
    	}
    	for(int i=1;i<=n;i++)
    	jc[i]=(jc[i-1]*i)%P,inv[i]=ksm(jc[i],P-2)%P;
    	for(int i=1;i<=n;i++)w[i]=(1<<i-1);
    	for(int i=1;i<=n;i++)
    	for(int j=i+1;j<=n;j++)
    	if(s[i][j])w[i]+=(1<<j-1),w[j]+=(1<<i-1);
    	f[0][0]=1;
    	for(int i=0;i<=Lim;i++)
    	cnt[i]=popcount(i);
    	for(int i=0;i<=Lim;i++)
    	for(int k=1;k<=n;k++)
    	if(((1<<k-1)&i)==0){
    		int v=i|w[k];
    		int x=cnt[w[k]]-cnt[i&w[k]]-1;
    		int t=n-cnt[i]-1;
    		for(int j=0;j<=n;j++)
    		if(f[i][j])f[v][j+1]=(f[v][j+1]+f[i][j]*A(t,x)%P)%P;
    	}
    	for(int i=n;i>=0;i--)
    	if(f[Lim][i]){
    		printf("%lld
    ",(f[Lim][i]*inv[n])%P);
    		return 0;
    	}
    }
    
  • 相关阅读:
    CSS盒子模型
    getContextPath、getServletPath、getRequestURI、request.getRealPath的区别
    MYSQL中的CASE WHEN END AS
    单点登录的精华总结
    git&github
    June 21st 2017 Week 25th Wednesday
    June 20th 2017 Week 25th Tuesday
    June 19th 2017 Week 25th Monday
    June 18th 2017 Week 25th Sunday
    June 17th 2017 Week 24th Saturday
  • 原文地址:https://www.cnblogs.com/Romeolong/p/10058991.html
Copyright © 2011-2022 走看看