Cod sursa(job #321945)

Utilizator perticas_catalinperticas catalin perticas_catalin Data 7 iunie 2009 20:20:05
Problema Cowfood Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.53 kb
#include<stdio.h>
#include<string.h>
FILE*fin=fopen("cowfood.in","r");
FILE*fout=fopen("cowfood.out","w");

#define maxs 10005
#define maxk 35
#define mod 3210121
#define min(a,b)((a)<(b)?(a):(b))
#define max(a,b)((a)>(b)?(a):(b))

int a[maxk][maxk],comb[maxs+maxk][maxk],ac[maxk][maxk],sol[maxk];
int n,k,s,ans,dim=0,acsum=0,ansr=0;
void back(int pas)
{
   int i;  
   // case 1  
   dim++;
   for(i=1;i<=k;i++)
   {
     ac[dim][i]=max(a[pas][i],ac[dim-1][i]);
     acsum-=ac[dim-1][i];
     acsum+=ac[dim][i];
   }  
   if(pas<n) back(pas+1);
   else if(acsum<=s)
        {
          if(dim%2) ansr+=comb[k+s-acsum][k];    
          else ansr-=comb[k+s-acsum][k];    
          if(ansr<0) ansr+=mod;
          if(ansr>=mod) ansr-=mod;
        }
   //repair
   for(i=1;i<=k;i++)
   {
     acsum+=ac[dim-1][i];
     acsum-=ac[dim][i];
   }       
   dim--;
   
   //case 0
   if(pas<n) back(pas+1);
   else 
   if(acsum<=s&&dim)
        {
          if(dim%2) ansr+=comb[k+s-acsum][k];    
          else ansr-=comb[k+s-acsum][k];    
          if(ansr<0) ansr+=mod;
          if(ansr>=mod) ansr-=mod;
        }
   
}
int main()
{
  int i,j,c,nrl,sum;
    
  fscanf(fin,"%d%d%d",&k,&s,&n);
  
  for(i=1;i<=n;i++)
    for(j=1;j<=k;j++)
      fscanf(fin,"%d",&a[i][j]);
      
  //calcul combinari    
  //(numarul de modalitati de a distribui cel mult nrob obiecte identice in c cutii este comb[nrob+c][c])
  
  comb[0][0]=1;    
  
  for(i=1;i<=k+s;i++)
  {
    comb[i][0]=1;
    for(j=1;j<=min(k,i);j++)
    {
      comb[i][j]=comb[i-1][j-1]+comb[i-1][j];
      if(comb[i][j]>mod) comb[i][j]-=mod;
    }  
  }
  /*
  ans=0;
  for(i=k;i<=s;i++)  
  {
    ans+=comb[i-1][k-1];  
    if(ans>mod) ans-=mod;
  } 
  */ 
  ans=(comb[k+s][k]-s*k-1+mod)%mod;
  //fprintf(fout,"%d",ans);
  
  
  
  if(n<=15) //solutie x puncte
  {
  for(c=1;c<(1<<n);c++)
  {
    nrl=0;    
    sum=0;               
    memset(ac[1],0,sizeof(ac[1]));
    
    for(i=0;i<n;i++)
      if((1<<i)&c)
      {
        nrl++;
        for(j=1;j<=k;j++)
          ac[1][j]=max(ac[1][j],a[i+1][j]);
      }
    for(j=1;j<=k;j++)
      sum+=ac[1][j];
      
    if(sum>s) continue;
    
    if(nrl%2) ansr+=comb[k+s-sum][k];    
    else ansr-=comb[k+s-sum][k];    
    if(ansr<0) ansr+=mod;
    if(ansr>=mod) ansr-=mod;
  }
  }
  else  back(1); //solutie mai buna
  
  
  ans=ans-ansr;
  if(ans<0) ans+=mod;
  ans=ans%mod;
  fprintf(fout,"%d",ans);
  fclose(fin);
  fclose(fout);
  return 0;
}