HDU 5464:Clarke and problem
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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。