您的位置:首页 > 移动开发

HDU 5119 Happy Matt Friends(01背包)

2020-04-25 07:42 686 查看

题意:给出一串序列,选择任意数使得异或和大于m,求有多少种方法。

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.

题解:01背包
因为异或值会冲突,用二维数组存储。
dp[i][j]dp[i][j]dp[i][j]:前iii个中选,异或和为jjj的方法数 = 第iii个选或不选
可以得到转移方程:

dp[i][j] = dp[i - 1][j] + dp[i - 1][j ^ a[i]];

用滚动数组会快很多,注意位运算的优先级。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
const int maxn = (1 << 20) - 1;
int t, n, m, a[45], dp[2][maxn + 5];
int main() {
scanf("%d", &t);
int cas = 0;
while (t--) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= maxn; j++) {
dp[i % 2][j] = dp[(i - 1) % 2][j] + dp[(i - 1) % 2][j ^ a[i]];
}
}
ll ans = 0;
for (int i = m; i <= maxn; i++) ans += dp[n % 2][i];
printf("Case #%d: %lld\n", ++cas, ans);
}
return 0;
}
  • 点赞
  • 收藏
  • 分享
  • 文章举报
gongyuandaye 发布了63 篇原创文章 · 获赞 0 · 访问量 827 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: