首页 > 技术文章 > HDU 5119 Happy Matt Friends(递推)

zyb993963526 2018-05-15 14:22 原文

http://acm.hdu.edu.cn/showproblem.php?pid=5119

题意:
给出n个数和一个上限m,求从这n个数里取任意个数做异或运算,最后的结果不小于m有多少种取法。

 

思路:
dp[i][j]表示在前i个数中取数做异或运算最后结果为j的方法数,那么dp[i][j] = dp[i-1][j] + dp[i-1][j^a[i]],分别对于取与不取这两种状态。

因为要推导出第i的状态只有i-1有关,所以这里可以用滚动数组。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn = (1<<20)+5;
 7 
 8 long long n, m;
 9 long long a[45];
10 long long dp[2][maxn];
11 
12 int main()
13 {
14     //freopen("in.txt","r",stdin);
15     int T;
16     int kase = 0;
17     scanf("%d",&T);
18     while(T--)
19     {
20         scanf("%lld%lld",&n,&m);
21         for(int i=1;i<=n;i++)  scanf("%lld",&a[i]);
22         memset(dp,0,sizeof(dp));
23         dp[0][0] = 1;
24         for(int i=1;i<=n;i++)
25         {
26             for(long long j=0;j<maxn-5;j++)
27             {
28                 dp[i%2][j] = dp[(i-1)%2][j] + dp[(i-1)%2][a[i]^j];
29             }
30         }
31         long long ans = 0;
32         for(long long i=m;i<maxn-5;i++)  ans += dp[n%2][i];
33         printf("Case #%d: %lld\n", ++kase, ans);
34     }
35     return 0;
36 }

 

推荐阅读