題目簡述spa
給定一個大小爲 n的序列(n<=10)R,要求你計算序列A0, A1, ..., AN-1的數量,要求A序列知足A0 + A1 + ... + AN-1 = A0 | A1 | ... | AN-1(0<=Ai<=R[i])code
題解blog
把n個數當作二進制,若是要求n個數的和等於n個數的或值,那麼對於n個數的每一位,最多隻可能有一個1,由於超過一個一就會產生進位。get
因爲第i個數若是當前位放置的是0,但 R[i]的當前位是1,那麼以後的位置上就能夠隨意放了,沒有限制,因此咱們能夠用DP[i][j]表示在第i位,當前狀態爲j的符合要求的方案數有多少(j的二進制中1表示放置的數沒有限制,否則就是有限制),用記憶化搜索很好實現~~it
代碼:class
1 #define MOD 1000000009; 2 ll dp[65][1111]; 3 vector<ll>r; 4 int n; 5 ll DP(int i, int mask) 6 { 7 if (i == -1) return 1; 8 ll &ret = dp[i][mask]; 9 if(ret!=-1) return ret; 10 ret=0; 11 int next = mask; 12 for (int t = 0; t < n; t++) 13 if (r[t] & (1LL << i)) 14 next |= (1 << t); 15 ret += DP(i - 1, next); 16 ret%=MOD; 17 for (int t = 0; t < n; t++) 18 if (mask & (1 << t)) 19 { 20 ret += DP(i - 1, next); 21 ret %= MOD; 22 } 23 else if (r[t] & (1LL << i)) 24 { 25 ret += DP(i - 1, next ^ (1 << t)); 26 ret %= MOD; 27 } 28 return ret; 29 } 30 class YetAnotherORProblem 31 { 32 public: 33 int countSequences(vector<long long> R) 34 { 35 n = R.size(); 36 r = R; 37 memset(dp, -1, sizeof(dp)); 38 return DP(60, 0); 39 } 40 };