Introduction

This is my blog of programming, I take notes and leave codes of computer science problems I solved here. Be my guest to comment :)

Thursday, December 6, 2012

uva 10616 - Divisible Group Sums


/*
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];
}
//-------------------------------

1 comment:

  1. how are you making sure that one element is not considered more than once

    ReplyDelete