Divisible Group Sums

Divisible Group Sums

Given a list of N numbers you will be allowed to choose any M of them. So you can choose in NCM ways. You will have to determine how many of these chosen groups have a sum, which is divisible by D.

Input

Input starts with an integer T (≤ 20), denoting the number of test cases.

The first line of each case contains two integers N (0 < N ≤ 200) and Q (0 < Q ≤ 10). Here N indicates how many numbers are there and Q is the total number of queries. Each of the next N lines contains one 32 bit signed integer. The queries will have to be answered based on these N numbers. Each of the next Q lines contains two integers D (0 < D ≤ 20) and M (0 < M ≤ 10).

Output

For each case, print the case number in a line. Then for each query, print the number of desired groups in a single line.

Sample Input

2

10 2

1

2

3

4

5

6

7

8

9

10

5 1

5 2

5 1

2

3

4

5

6

6 2

Sample Output

Case 1:

2

9

Case 2:

1

分析:dp[i][j][k][t]表示前i个选了j个%k=t的方案数,转移一下即可;

   本质是一个01背包;

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <climits>
#include <cstring>
#include <string>
#include <set>
#include <bitset>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#define rep(i,m,n) for(i=m;i<=n;i++)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define vi vector<int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ll long long
#define pi acos(-1.0)
#define pii pair<int,int>
#define sys system("pause")
const int maxn=1e5+10;
const int N=2e2+10;
using namespace std;
ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
int n,m,k,t,a[N],cas;
ll dp[N][11][21][20];
int main()
{
    int i,j;
    scanf("%d",&t);
    while(t--)
    {
        int q;
        memset(dp,0,sizeof(dp));
        rep(i,1,20)dp[0][0][i][0]=1;
        scanf("%d%d",&n,&q);
        rep(i,1,n)scanf("%d",&a[i]);
        rep(i,1,n)rep(j,0,min(i,10))rep(k,1,20)rep(m,0,k-1)
        {
            dp[i][j][k][m]+=dp[i-1][j][k][m];
            if(j)dp[i][j][k][m]+=dp[i-1][j-1][k][((m-a[i])%k+k)%k];
        }
        printf("Case %d:\n",++cas);
        while(q--)
        {
            int b,c;
            scanf("%d%d",&b,&c);
            printf("%lld\n",dp[n][c][b][0]);
        }
    }
    return 0;
}
posted @ 2017-03-11 11:03  mxzf0213  阅读(171)  评论(0编辑  收藏  举报