DP - 01背包 - Happy Matt Friends - HDU - 5119
题意:
T 组 测 试 用 例 , 每 组 包 括 整 数 n 和 m , 以 及 一 个 长 度 为 n 的 序 列 a i 。 T组测试用例,每组包括整数n和m,以及一个长度为n的序列a_i。 T组测试用例,每组包括整数n和m,以及一个长度为n的序列ai。
在 这 n 个 数 中 选 择 一 些 数 , 使 得 这 些 数 的 异 或 值 大 于 等 于 m , 问 一 共 有 多 少 种 方 案 。 在这n个数中选择一些数,使得这些数的异或值大于等于m,问一共有多少种方案。 在这n个数中选择一些数,使得这些数的异或值大于等于m,问一共有多少种方案。
Sample Input:
2
3 2
1 2 3
3 3
1 2 3
Sample Output:
Case #1: 4
Case #2: 2
数据范围:
n < = 40 , m < = 1 0 6 , a i < = 1 0 6 。 T i m e l i m i t : 6000 m s , M e m o r y l i m i t : 510000 k B n<=40,m<=10^6,a_i<=10^6。\\Time\ limit:6000 ms,Memory \ limit:510000 kB n<=40,m<=106,ai<=106。Time limit:6000ms,Memory limit:510000kB
分析:
一 个 比 较 明 显 的 01 背 包 问 题 , 只 是 把 体 积 限 制 改 成 了 异 或 值 的 大 小 。 一个比较明显的01背包问题,只是把体积限制改成了异或值的大小。 一个比较明显的01背包问题,只是把体积限制改成了异或值的大小。
状 态 表 示 , f [ i ] [ j ] : 考 虑 前 i 个 数 , 且 异 或 值 不 超 过 j 的 方 案 总 数 。 状态表示,f[i][j]:考虑前i个数,且异或值不超过j的方案总数。 状态表示,f[i][j]:考虑前i个数,且异或值不超过j的方案总数。
状
态
计
算
:
①
、
不
包
含
第
i
个
数
:
f
[
i
]
[
j
]
=
f
[
i
−
1
]
[
j
]
。
②
、
包
含
第
i
个
数
:
f
[
i
]
[
j
]
=
f
[
i
−
1
]
[
j
状态计算:\\①、不包含第i个数:f[i][j]=f[i-1][j]。\\②、包含第i个数:f[i][j]=f[i-1][j
状态计算:①、不包含第i个数:f[i][j]=f[i−1][j]。②、包含第i个数:f[i][j]=f[i−1][j^
a
[
i
]
]
。
(
这
由
异
或
的
性
质
容
易
得
到
)
。
a[i]]。(这由异或的性质容易得到)。
a[i]]。(这由异或的性质容易得到)。
那
么
总
的
方
案
就
是
二
者
相
加
:
f
[
i
]
[
j
]
=
f
[
i
−
1
]
[
j
]
+
f
[
i
−
1
]
[
j
那么总的方案就是二者相加:f[i][j]=f[i-1][j]+f[i-1][j
那么总的方案就是二者相加:f[i][j]=f[i−1][j]+f[i−1][j^
a
[
i
]
]
。
a[i]]。
a[i]]。
注意:
① 、 因 为 序 列 中 的 元 素 上 限 为 1 0 6 , 二 进 制 形 式 下 有 21 位 , 因 此 在 异 或 的 情 况 下 可 能 会 达 到 2 20 , 第 二 维 空 间 应 当 大 于 这 个 值 。 ①、因为序列中的元素上限为10^6,二进制形式下有21位,因此在异或的情况下可能会达到2^{20},\\\qquad第二维空间应当大于这个值。 ①、因为序列中的元素上限为106,二进制形式下有21位,因此在异或的情况下可能会达到220,第二维空间应当大于这个值。
② 、 第 二 层 循 环 应 当 要 枚 举 到 第 二 维 的 上 限 , 因 为 我 们 的 状 态 定 义 的 是 不 超 过 j , 最 后 要 求 的 应 当 是 ∑ i = m 2 20 f [ n ] [ i ] 。 ②、第二层循环应当要枚举到第二维的上限,因为我们的状态定义的是不超过j,最后要求的应当是\sum_{i=m}^{2^{20}}f[n][i]。 ②、第二层循环应当要枚举到第二维的上限,因为我们的状态定义的是不超过j,最后要求的应当是∑i=m220f[n][i]。
③ 、 f 数 组 应 当 开 l l 类 型 , 否 则 会 爆 i n t 。 ③、f数组应当开ll类型,否则会爆int。 ③、f数组应当开ll类型,否则会爆int。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#define ll long long
using namespace std;
const int N=50,M=1<<20;
int T,n,m,a[N];
ll f[N][M];
int main()
{
cin>>T;
for(int t=1;t<=T;t++)
{
memset(f,0,sizeof f);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
f[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<M;j++)
f[i][j]=f[i-1][j]+f[i-1][j^a[i]];
ll res=0;
for(int i=m;i<M;i++) res+=f[n][i];
printf("Case #%d: %lld\n",t,res);
}
return 0;
}