HDU-5119(状压dp)

Happy Matt Friends

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


 

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 ≤ 106).

In the second line, there are N integers ki (0 ≤ ki ≤ 106), 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亚洲区北京站-重现赛(感谢北师和上交)

 

 

Recommend

 

liuyiding

 

//枚举状态: 共有2^40种(取与不取)
//探索转移: 当前状态的种类数==取当前这个数该状态的种类+不取当前这个数该状态的种类
#include
#include
#include
#include
using namespace std;
#define MAXN 45
int m,n;
int a[MAXN];
long long dp[2][(1<<20)+5]; //状压dp开的空间是比种类数多1位的,dp[i][j]的j表示产生这个异或值得种类
int main()
{
    int t,cnt=0;
    int i,j;
    scanf("%d",&t);
    while(t--)
   {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
        sort(a,a+n);
        memset(dp,0,sizeof(dp));
        dp[0][0]=1;
        for(i=1;i<=n;i++)
        {
            for(j=0;j<(1<<20);j++)//每个数都有两种状态,取或者不取
            dp[i%2][j]=dp[(i-1)%2][j]+dp[(i-1)%2][j^a[i]];//只有两个i状态,当前状态,和之前状态。
        }                                                 //第1个j是不取该数,第2个是取该数
        long long ans=0;
        for(i=m;i<(1<<20);++i)
        {
            ans+=dp[n%2][i];
        }
        printf("Case #%d: %lld\n",++cnt,ans);
    }
    return 0;
}

 

你可能感兴趣的:(c++,状压dp)