Description
龙神有很多背包,每一个背包都有一个容积。但是这些背包的容积都恰好是一个数字
V
V
V的整数倍,比如
V
V
V,
2
V
2V
2V等等。并且对于任意
k
≥
1
k \geq 1
k≥1,容积为
k
×
V
k \times V
k×V的背包都存在。
龙神有一些物品要装进背包,第
i
i
i 个物品占据的体积
p
i
p_i
pi。现在,龙神想选出一些物品,使得存在一个背包可以恰好放下这些物品,并且这个背包放满。
龙神想知道这样的取法有多少个,请你帮他算一算吧?由于取法很多,你只需要输出取法的末七位数,没有前导零,即可(即对10000000取模)。
Input
第一行两个数
n
,
V
n, V
n,V,分别表示物品数和背包体积的基数。
第二行
n
n
n个数,分别表示每个物品的体积
p
i
p_i
pi。
Output
输出一行一个数,表示取法总数的末七位。
Note
数据保证 1 ≤ n , V ≤ 2000 , 1 ≤ p i ≤ 100000 1 \leq n, V \leq 2000, 1 \leq p_i \leq 100000 1≤n,V≤2000,1≤pi≤100000。
用例 | 测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 |
---|---|---|---|---|---|
测试用例 1 |
| 3↵ | 1秒 | 64M | 0 |
思路
在存储时可以先对 V V V 取余简化。
背包容量 0 → v − 1 0 \rightarrow v-1 0→v−1,放 i 物品和不放 i 物品分别计算。同时注意循环中背包容量下标不要越界,大了取余,小了 v v v 。同时每次运算对 1 e 7 1e7 1e7 取模。
最后输出背包容量为“0”(取模后为零)时的值。注意减去真正为0的一种方案.
代码
#include <stdio.h>
#define N 2005
#define M 10000000
int wp[N] = {0}, dp[N][N] = {0};
int max(int a, int b)
{
return a > b ? a : b;
}
int main(int argc, char const **argv)
{
int n, v, i, j, temp;
scanf("%d %d", &n, &v);
for (i = 1; i <= n; i++)
{
scanf("%d", &temp);
temp %= v;
wp[i] = temp ;
}
// for(i=1;i<=n;i++) printf("%d ",wp[i]);
dp[0][0]=1;
for (i = 1; i <= n; i++)
{
for (j = 0; j <= v-1; j++)
{
dp[i][j]+=dp[i-1][j];
dp[i][j]%=M;
if(j>=wp[i])
dp[i][j]+=dp[i-1][j-wp[i]];
else dp[i][j]+=dp[i-1][j-wp[i]+v];
dp[i][j]%=M;
}
}
printf("%d\n", dp[n][0]-1);
return 0;
}