SRM 508 DIV1 500pt(DP)

題目簡述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 };
相關文章
相關標籤/搜索