hdu5119 Happy Matt Friends [01背包 + 异或和]

题意:

给你n个数字, 和m,让你求从这n个数字里面抽取若干个数字, 其异或和不小于m的方案数。

题解:

m的取值范围不超过 1000000

建一个二维的dp数组,通过滚动来进行dp

状态转移方程式为:dp[i%2][j] = dp[(i-1)%2][j] + dp[(i-1)%2][j^num[i]];

dp[(i-1)%2][j] 代表不取num[i]的的异或和为j的方案数

dp[(i-1)%2][j^num[i]]   代表取num[i]的的异或和为j的方案数   j^num[i]^num[i] = j

/*
Algorithm:
Author: anthony1314
Creat Time:
Time Complexity:
*/

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cstring>
#include<cstdio>
//#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define mod 1e9 + 7
#define line printf("--------------\n");
using namespace std;
ll dp[2][2*1000005];
int num[45];
int main() {
    int t;
    cin>>t;
    int cc = 1;
    while(t--) {
        int n, m;
        cin>>n>>m;
        for(int i = 1; i <= n; i++) {
            scanf("%d", &num[i]);
        }
        memset(dp,0, sizeof(dp));
        dp[0][0] = 1;
        for(int i = 1; i <= n; i++) {
            for(int j = 0; j < 1<<20; j++) {
                dp[i%2][j] = dp[(i-1)%2][j] + dp[(i-1)%2][j^num[i]];
//                cout<<dp[i%2][j]<<endl;
            }
        }
        ll sum = 0;
        for(int i = m; i < 1<<20; i++) {
            sum+=dp[n % 2][i]; 
        }
        printf("Case #%d: ",cc++);
        cout<<sum<<endl;
    }


    return 0;
}

 

全部评论

相关推荐

01-05 09:14
同济大学 Java
不要盒我呀:我要是9✌🏻我就选保研,保研了大四再找实习,实习之后,如果觉得自己不适合互联网工作模式,还能有其他选择,如果实习后决定了走互联网,也能提升学历提高竞争力
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务