【BZOJ4903】【CTSC2017】吉夫特 [DP]

吉夫特

Time Limit: 15 Sec  Memory Limit: 512 MB
[Submit][Status][Discuss]

Description

  

Input

  第一行一个整数n。
  接下来n行,每行一个整数,这n行中的第i行,表示ai。

Output

    一行一个整数表示答案。

Sample Input

  4
  15
  7
  3
  1

Sample Output

  11

HINT

  

Main idea

  给定一个序列,问有多少个子序列满足相邻的数构成的组合数都为奇数。

Solution

  首先我们用Lucas定理推一推可以知道:C(n,m)为奇数当且仅当n&m=m

  有了这个定理就好办了,我们可以显然地想到DP:通过枚举数在二进制下的子集转移,这样保证了可以转移过去。

  由于序列每个数都不同,且最大值为233333,所以效率是O(3^18)的。

Code

 1 #include<iostream>    
 2 #include<string>    
 3 #include<algorithm>    
 4 #include<cstdio>    
 5 #include<cstring>    
 6 #include<cstdlib>
 7 #include<cmath>
 8 using namespace std;  
 9  
10 const int ONE = 300005;
11 const int MOD = 1e9+7;
12  
13 int n,x;
14 int f[ONE];
15 int Ans;
16  
17 int get()
18 {    
19         int res=1,Q=1;char c;    
20         while( (c=getchar())<48 || c>57 ) 
21         if(c=='-')Q=-1; 
22         res=c-48;     
23         while( (c=getchar())>=48 && c<=57 )    
24         res=res*10+c-48;    
25         return res*Q;
26 }
27  
28 int main()  
29 {
30         n = get();
31         for(int i=1; i<=n; i++)
32         {
33             x = get();
34             int record = (f[x] + 1) % MOD;
35             for(int sub=x; sub; sub=(sub-1) & x)
36                 f[sub] = (f[sub] + record) % MOD;
37             Ans = (Ans + record) % MOD; 
38         }
39         printf("%d", Ans-n);
40 }
View Code

 

posted @ 2017-05-26 14:33  BearChild  阅读(523)  评论(0编辑  收藏  举报