/*
Problem link
Type: DP, Mathematics
Algorithm:
Let f(i,j,k) is the number of ways to choose i elements from a[1..j] so that
their sum divides d gives the remainder of k.
The function sub(x,y) returns the remainder of a number which y+that number
divides d gives the remainder of x. For example:
For d = 5, sub(3,7) = 1 this mean any number divides d gives the remainder of 1
plus 7 divides d gives the remainder of 3.
Now we can come up with a formula for f(i,j,k):
if we choose the number a[j] to add to the sum so it divides d gives remainder k
then before that, the remainder of the previous sum must have been
chosen from a[1..j-1] and divides d gives
remainder sub(k,a[j]%d). Hence f(i-1,j-1,sub(k,a[j]%d))
if we dont choose the number a[j], the previous sum must be chosen from a[1..j-1]
with remainder k. Hence f(i,j-1,k)
Therefore: f(i,j,k) = f(i,j-1,k)+f(í-1,j-1,sub(k,a[j]%d));
Initially: f[0][j][0] is equal to 1 for all j, this mean if we dont choose any thing,
the sum is = which divides d gives remainder 0.
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
using namespace std;
const int maxn = 210;
const int maxm = 25;
//-------------------------------
int a[maxn];
long long f[maxm][maxn][maxm];
int n,m,q,d;
//-------------------------------
void solve();
int sub(int x, int y);
//-------------------------------
int main() {
int test = 0;
while (true)
{
cin >> n >> q;
if (n==0 && q==0) break;
test++;
printf("SET %d:\n",test);
for (int i=1; i<=n; i++) cin >> a[i];
for (int i=1; i<=q; i++)
{
cin >> d >> m;
printf("QUERY %d: ",i);
solve();
cout << endl;
}
}
return 0;
}
//-------------------------------
int sub(int x, int y)
{
int tmp = (x-y)%d;
if (tmp>=0) return(tmp);
return(tmp+d);
}
//-------------------------------
void solve() {
for (int i=0; i<=m; i++)
for (int j=0; j<=n; j++)
for (int k=0; k<=d-1; k++) f[i][j][k] = 0;
for (int i=0; i<=n; i++) f[0][i][0] = 1;
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
for (int k=0; k<=d-1; k++)
f[i][j][k] = f[i][j-1][k]+f[i-1][j-1][sub(k,a[j]%d)];
cout << f[m][n][0];
}
//-------------------------------
how are you making sure that one element is not considered more than once
ReplyDelete