zoukankan      html  css  js  c++  java
  • loj2540 「PKUWC 2018」随机算法

    pkusc 快到了……做点题涨涨 rp。

    (f(S,i)) 表示 (S) 这个集合是决计不能选的(要么属于独立集,要么和独立集相连),或称已经考虑了的,(i) 表示此集合对应的最大独立集大小。那么枚举一下哪些点 (j) 不在 (S) 里,记 (w_i) 表示 (i) 和与之相邻的点集,则 (f(S cup w_j,i+1) leftarrow f(S cup w_j,i+1) + f(S,i) imes A_{n-|S|-1}^{|w_j-(w_j cap S)|-1})

    然而对于一个集合 (S),它的最大独立集大小是确定的,那么就来一个数组 (mx_S) 来记录其最大独立集大小。当最大独立集大小更新之时,(dp_S) 就清零然后再计数就行了。复杂度从 (O()跑得过()) 变成了 (O()更跑得过()),也就是(O(n^22^n)) 变成了 (O(n2^n))……。

    改进前:

    #include <iostream>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    int n, m, w[25], uu, vv, jie[25], inv[25], dp[25][1050005], cnt[1050005];
    const int mod=998244353;
    int A(int x, int y){
    	// if(x<y)	return 0;
    	return (ll)jie[x]*inv[x-y]%mod;
    }
    int main(){
    	cin>>n>>m;
    	for(int i=1; i<=m; i++){
    		scanf("%d %d", &uu, &vv);
    		uu--; vv--;
    		w[uu] |= 1<<vv;
    		w[vv] |= 1<<uu;
    	}
    	jie[0] = jie[1] = inv[0] = inv[1] = 1;
    	for(int i=2; i<=n; i++){
    		jie[i] = (ll)jie[i-1] * i % mod;
    		inv[i] = (ll)(mod - mod / i) * inv[mod%i] % mod;
    	}
    	for(int i=0; i<n; i++)
    		w[i] |= 1<<i;
    	for(int i=2; i<=n; i++)
    		inv[i] = (ll)inv[i-1] * inv[i] % mod;
    	for(int i=0; i<(1<<n); i++)
    		for(int j=0; j<n; j++)
    			if(i&(1<<j))
    				cnt[i]++;
    	dp[0][0] = 1;
    	for(int i=0; i<n; i++)
    		for(int s=0; s<(1<<n); s++)
    			if(dp[i][s])
    				for(int j=0; j<n; j++)
    					if(!(s&(1<<j)))
    						dp[i+1][s|w[j]] = (dp[i+1][s|w[j]] + (ll)dp[i][s] * A(n-cnt[s]-1, cnt[w[j]-(w[j]&s)]-1)%mod) % mod;
    	for(int i=n; i; i--)
    		if(dp[i][(1<<n)-1]){
    			cout<<(ll)dp[i][(1<<n)-1]*inv[n]%mod<<endl;
    			return 0;
    		}
    	return 0;
    }
    

    改进后:

    #include <iostream>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    int n, m, w[25], uu, vv, jie[25], inv[25], dp[1050005], cnt[1050005];
    int mx[1050005];
    const int mod=998244353;
    int A(int x, int y){
    	// if(x<y)	return 0;
    	return (ll)jie[x]*inv[x-y]%mod;
    }
    int main(){
    	cin>>n>>m;
    	for(int i=1; i<=m; i++){
    		scanf("%d %d", &uu, &vv);
    		uu--; vv--;
    		w[uu] |= 1<<vv;
    		w[vv] |= 1<<uu;
    	}
    	jie[0] = jie[1] = inv[0] = inv[1] = 1;
    	for(int i=2; i<=n; i++){
    		jie[i] = (ll)jie[i-1] * i % mod;
    		inv[i] = (ll)(mod - mod / i) * inv[mod%i] % mod;
    	}
    	for(int i=0; i<n; i++)
    		w[i] |= 1<<i;
    	for(int i=2; i<=n; i++)
    		inv[i] = (ll)inv[i-1] * inv[i] % mod;
    	for(int i=0; i<(1<<n); i++)
    		for(int j=0; j<n; j++)
    			if(i&(1<<j))
    				cnt[i]++;
    	dp[0] = 1;
    	for(int s=0; s<(1<<n); s++)
    		if(dp[s])
    			for(int i=0; i<n; i++)
    				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] = (dp[t] + (ll)dp[s] * A(n-cnt[s]-1, cnt[w[i]-(w[i]&s)]-1)%mod) % mod;
    				}
    	cout<<(ll)dp[(1<<n)-1]*inv[n]%mod<<endl;
    	return 0;
    }
    
  • 相关阅读:
    动态生成 Excel 文件供浏览器下载的注意事项
    JavaEE 中无用技术之 JNDI
    CSDN 泄露用户密码给我们什么启示
    刚发布新的 web 单点登录系统,欢迎下载试用,欢迎提建议
    jQuery jqgrid 对含特殊字符 json 数据的 Java 处理方法
    一个 SQL 同时验证帐号是否存在、密码是否正确
    PostgreSQL 数据库在 Windows Server 2008 上安装注意事项
    快速点评 Spring Struts Hibernate
    Apache NIO 框架 Mina 使用中出现 too many open files 问题的解决办法
    解决 jQuery 版本升级过程中出现 toLowerCase 错误 更改 doctype
  • 原文地址:https://www.cnblogs.com/poorpool/p/9069285.html
Copyright © 2011-2022 走看看