Happy Matt Friends(利用滚动数组优化数组空间的DP)



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



Happy Matt Friends

Time Limit: 6000/6000 MS (Java/Others)    Memory Limit: 510000/510000 K (Java/Others)
Total Submission(s): 1718    Accepted Submission(s): 681


Problem Description
Matt has N friends. They are playing a game together.

Each of Matt’s friends has a magic number. In the game, Matt selects some (could be zero) of his friends. If the xor (exclusive-or) sum of the selected friends’magic numbers is no less than M , Matt wins.

Matt wants to know the number of ways to win.
 

Input
The first line contains only one integer T , which indicates the number of test cases.

For each test case, the first line contains two integers N, M (1 ≤ N ≤ 40, 0 ≤ M ≤ 10 6).

In the second line, there are N integers ki (0 ≤ k i ≤ 10 6), indicating the i-th friend’s magic number.
 

Output
For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y indicates the number of ways where Matt can win.
 

Sample Input
 
   
2 3 2 1 2 3 3 3 1 2 3
 

Sample Output
 
   
Case #1: 4 Case #2: 2
Hint
In the first sample, Matt can win by selecting: friend with number 1 and friend with number 2. The xor sum is 3. friend with number 1 and friend with number 3. The xor sum is 2. friend with number 2. The xor sum is 2. friend with number 3. The xor sum is 3. Hence, the answer is 4.
 

Source
2014ACM/ICPC亚洲区北京站-重现赛(感谢北师和上交)
 


题意:n个数,可以取其中一部分来异或,问全部异或结果不小于m有多少种取法。


编程思想:dp(背包)。dp(i,j)表示取到第i个数,异或结果为j,有多少种方法。初态是有一种取法取得0,然后对每个数,有两种选择,取或不取,加上上一步的路径数就可以了。最后将dp(n,j)中j>=m的部分求和就行。需要注意的是,会爆int。分析由于n<=40&&m<=10^6,因此我们可以枚举所有可能的异或值,时间复杂度40*10^6。采用动态规划的思想,转态转移方程为:dp[i&1][j]=d[(i-1)&1][j]+d[(i-1)&1][j^a[i]];由于40*10^6太大,所以此处我们采用滚动数组。


AC code:

#include
#include
#include
#include
#include
#include
#include
#define LL long long
using namespace std;
const int maxn=1<<20;
int dp[2][maxn];
int ki[44];

//dp[i&1][j]=dp[(i-1)&1][j]+dp[(i-1)&1][j^ki[i]];

LL ans;
int main()
{
    //freopen("D:\\in.txt","r",stdin);
    //printf("%lf\n",log(1000000.0)*1.0/log(2.0));
    int T,n,m,i,j,cas;
    scanf("%d",&T);
    for(cas=1;cas<=T;cas++)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&ki[i]);
        }
        memset(dp,0,sizeof(dp));
        dp[0][0]=1;
        for(i=1;i<=n;i++)
        {
            for(j=0;j






你可能感兴趣的:(HDU,动态规划,ACM)