zoukankan      html  css  js  c++  java
  • 牛客 P21336 和与或 (数位dp)

    大意: 给定数组$R$, 求有多少个数组$A$, 满足$0le A_i le R_i$且$A_0+...+A_{N-1}=A_0space or ...space or space A_{N-1}$.

    题目条件等价于对于任意的$i,j$, 有$A_i and A_j = 0$, 所以每个二进制位上为$1$的最多只有一个数, 然后跑一次二进制数位$dp$即可.

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <string.h>
    #define REP(i,a,n) for(int i=a;i<=n;++i)
    #define PER(i,a,n) for(int i=n;i>=a;--i)
    using namespace std;
    typedef long long ll;
    const int P = 1e9+9;
    
    int n, dp[70][2000];
    ll r[20];
    
    //dp[x][y] 表示从二进制最高位填到第d位时, 无限制的a[i]的状态为now的方案数.
    int dfs(int d, int now) {
    	if (d<0) return 1;
    	int &ans = dp[d][now];
    	if (~ans) return ans;
    	int nxt = now;
    	REP(i,0,n-1) if (r[i]>>d&1) nxt |= 1<<i;
    	//第d位全为0的方案数
    	ans = dfs(d-1,nxt);
    	REP(i,0,n-1) {
    		//a[i]的第d位为1的方案数 
    		if (now>>i&1) { 
    			//a[i]无限制, 则下一步全无限制
    			ans = (ans+dfs(d-1,nxt))%P;
    		}
    		else if (nxt>>i&1) { 
    			//a[i]有限制, 且r[i]的第d位为1, 则下一步a[i]还有限制
    			ans = (ans+dfs(d-1,nxt^(1<<i)))%P;
    		}
    		//a[i]有限制, 且r[i]的第d位为0, 不能填1
    	}
    	return ans;
    }
    
    int main() {
    	scanf("%d", &n);
    	REP(i,0,n-1) scanf("%lld", r+i);
    	memset(dp,-1,sizeof dp);
    	printf("%d
    ", dfs(60,0));
    }
    
  • 相关阅读:
    git
    java网络
    配置本地git服务器(gitblit win7)
    atom 插件安装【转载】
    javaIo
    如何在eclipse中设置断点并调试程序
    如何将工程推到github上
    git操作记录
    编码
    node升级7.0以上版本使用gulp时报错
  • 原文地址:https://www.cnblogs.com/uid001/p/11033243.html
Copyright © 2011-2022 走看看