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)
问题描述
克拉克是一名人格分裂患者。某一天,克拉克分裂成了一个学生,在做题。 
突然一道难题难到了克拉克,这道题是这样的:  
给你nn个数,要求选一些数(可以不选),把它们加起来,使得和恰好是pp的倍数(00也是pp的倍数),求方案数。  
对于nn很小的时候,克拉克是能轻易找到的。然而对于nn很大的时候,克拉克没有办法了,所以来求助于你。  
输入描述
第一行一个整数T(1 \le T \le 10)T(1T10),表示数据的组数。  
每组数据第一行是两个正整数n, p(1 \le n, p \le 1000)n,p(1n,p1000)。  
接下来的一行有nn个整数a_i(|a_i| \le 10^9)ai(ai109),表示第ii个数。
输出描述
对于每组数据,输出一个整数,表示问题的方案数,由于答案很大,所以求出对10^9+7109+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;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

posted on 2015-09-20 10:56  光速小子  阅读(151)  评论(0编辑  收藏  举报

导航