Clarke and problem
Accepts: 130
Submissions: 781
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
克拉克是一名人格分裂患者。某一天,克拉克分裂成了一个学生,在做题。 突然一道难题难到了克拉克,这道题是这样的: 给你n个数,要求选一些数(可以不选),把它们加起来,使得和恰好是p的倍数(0也是p的倍数),求方案数。 对于n很小的时候,克拉克是能轻易找到的。然而对于n很大的时候,克拉克没有办法了,所以来求助于你。
输入描述
第一行一个整数T(1≤T≤10),表示数据的组数。 每组数据第一行是两个正整数n,p(1≤n,p≤1000)。 接下来的一行有n个整数ai(∣ai∣≤109),表示第i个数。
输出描述
对于每组数据,输出一个整数,表示问题的方案数,由于答案很大,所以求出对109+7的答案即可。
输入样例
1 2 3 1 2
输出样例
2
Hint
有两种方案:什么也不选;全都选。
做的时候自己看到ai的数值觉得太大就放弃了,结果原来p就是一个小于等于1000的数。
就是看余数啊,这种题自己也做过很多个了,为什么就是不长记性呢。。。
代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std;
const int mod = 1e9 + 7;
int test, n, p;
long long a[1005];
long long dp[1005][1005];
int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout);
int i, j;
cin >> test;
while (test--)
{
cin >> n >> p;
for (i = 1; i <= n; i++)
{
cin >> a[i];
a[i] = a[i] % p;
}
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (i = 1; i <= n; i++)
{
for (j = 0; j < p; j++)
{
dp[i][j] = (dp[i - 1][j] + dp[i - 1][(j + p - a[i]) % p]) % mod;
}
}
cout << dp[n][0] << endl;
}
//system("pause");
return 0;
}