1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > HDU5464 Clarke and problem

HDU5464 Clarke and problem

时间:2022-06-01 15:43:51

相关推荐

HDU5464 Clarke and problem

原题链接:http://acm./showproblem.php?pid=5464

Clarke and problem

Problem Description

Clarke is a patient with multiple personality disorder. One day, Clarke turned into a student and read a book.

Suddenly, a difficult problem appears:

You are given a sequence of number a1,a2,…,an and a number p. Count the number of the way to choose some of number(choose none of them is also a solution) from the sequence that sum of the numbers is a multiple of p(0 is also count as a multiple of p). Since the answer is very large, you only need to output the answer modulo 109+7109+7

Input

The first line contains one integer T(1≤T≤10) - the number of test cases.

T test cases follow.

The first line contains two positive integers n,p(1≤n,p≤1000)

The second line contains n integers a1,a2,…an(|ai|≤109).

Output

For each testcase print a integer, the answer.

Sample Input

1

2 3

1 2

Sample Output

2

Hint:

2 choice: choose none and choose all.

题目大意

克拉克是一名人格分裂患者。某一天,克拉克分裂成了一个学生,在做题。

突然一道难题难到了克拉克,这道题是这样的:

给你n个数,要求选一些数(可以不选),把它们加起来,使得和恰好是p的倍数(0也是p的倍数),求方案数。

对于n很小的时候,克拉克是能轻易找到的。然而对于n很大的时候,克拉克没有办法了,所以来求助于你。

题解

我们注意到p⩽1000p⩽1000,但是数据范围是109109,背包显然不可做。但是,考虑到我们只需要凑出p的倍数,那么dp就只跟模p的余数有关系,那么我们读入时就可以将每个数模p缩小数据范围。

接下来,我们用二维数组dp[i][j]dp[i][j]表示前ii个数可以凑出余数为j" role="presentation">j的方案数,那么就有状态转移方程:

dp[i][j]=dp[i−1][j]+dp[i−1][(j−x[i]+p)modp]dp[i][j]=dp[i−1][j]+dp[i−1][(j−x[i]+p)modp]

具体来讲,我们将每个数分为两个状态:

1.选了第ii个数,那么方案数就是前i−1" role="presentation">i1个数凑出余数为(j−x[i]+p)(j−x[i]+p)的方案数。

2.不选,那么显然跟dp[i−1][j]dp[i−1][j]一样。

代码

#include<bits/stdc++.h>#define ll long longusing namespace std;const int M=1005,mod=1e9+7;int x[M],n,p;ll dp[M][M];void in(){memset(dp,0,sizeof(dp));scanf("%d%d",&n,&p);for(int i=1;i<=n;++i)scanf("%d",&x[i]),x[i]%=p;}void ac(){dp[0][0]=1;for(int i=1;i<=n;++i)for(int j=0;j<=p;++j)dp[i][j]=(dp[i-1][j]+dp[i-1][(j-x[i]+p)%p])%mod;printf("%lld\n",dp[n][0]);}int main(){int T;scanf("%d",&T);for(int i=1;i<=T;++i)in(),ac();return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。