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;
}

 

全部评论

相关推荐

能干的三文鱼刷了100道题:公司可能有弄嵌入式需要会画pcb的需求,而且pcb能快速直观看出一个人某方面的实力。看看是否有面试资格。问你问题也能ai出来,pcb这东西能作假概率不高
点赞 评论 收藏
分享
05-12 16:04
已编辑
江西财经大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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