zoukankan      html  css  js  c++  java
  • bzoj 2734 集合悬殊 (状压dp)

    大意: 给定$n$, 求集合{1,2,...n}的子集数, 满足若$x$在子集内, 则$2x,3x$不在子集内.

    记$f(x)$为$x$除去所有因子2,3后的数, 那么对于所有$f$值相同的数可以划分为一个等价类, 对2的倍数和3的倍数建一个二维的表, 在表上做状压$dp$即可. 最后答案就为每个等价类方案的乘积.

    #include <iostream>
    #include <string.h>
    #define REP(i,a,n) for(int i=a;i<=n;++i)
    using namespace std;
    typedef long long ll;
    const int P = 1e9+1;
    
    const int N = 1e5+10;
    int n, vis[N];
    int a[30], s[1<<11];
    int dp[2][1<<11];
    
    int calc(int x) {
    	memset(dp,0,sizeof dp);
    	memset(a,0,sizeof a);
    	int dx = 0, dy = 0;
    	for (int i=1,t=x; t<=n; t*=2,++i) {
    		for (int j=1,tt=t; tt<=n; tt*=3,++j) {
    			(a[i]<<=1)|=1, vis[tt] = 1;
    			dx = max(dx, i);
    			dy = max(dy, j);
    		}
    	}
    	int mx = (1<<dy)-1, cnt = 0;
    	REP(i,0,mx) if (!(i&i<<1)) s[++cnt] = i;
    	int cur = 0;
    	dp[cur][1] = 1;
    	REP(i,1,dx) {
    		cur ^= 1;
    		memset(dp[cur],0,sizeof dp[cur]);
    		REP(j,1,cnt) if (dp[!cur][j]) {
    			REP(k,1,cnt) if (!(s[j]&s[k])&&(s[k]|a[i])==a[i]) {
    				dp[cur][k]=(dp[cur][k]+dp[!cur][j])%P;
    			}
    		}
    	}
    	int ans = 0;
    	REP(i,1,cnt) ans=(ans+dp[cur][i])%P;
    	return ans;
    }
    
    int main() {
    	scanf("%d", &n);
    	int ans = 1;
    	REP(i,1,n) if (!vis[i]) ans=(ll)ans*calc(i)%P;
    	printf("%d
    ", ans);
    }
    
  • 相关阅读:
    线性回归
    [C0] 引言(Introduction)
    [C5W2] Sequence Models
    [C5W3] Sequence Models
    [C4W4] Convolutional Neural Networks
    [C4W3] Convolutional Neural Networks
    [C4W2] Convolutional Neural Networks
    折腾ELK+kafka+zk
    helm 安装prometheus operator 并监控ingress
    练习calico的网络policy
  • 原文地址:https://www.cnblogs.com/uid001/p/10982037.html
Copyright © 2011-2022 走看看