Friday, 18 March 2016

1145 - Dice (I)
Time Limit: 2 second(s)Memory Limit: 32 MB
You have N dices; each of them has K faces numbered from 1 to K. Now you have arranged the N dices in a line. You can rotate/flip any dice if you want. How many ways you can set the top faces such that the summation of all the top faces equals S?
Now you are given N, K, S; you have to calculate the total number of ways.

Input

Input starts with an integer T (≤ 25), denoting the number of test cases.
Each case contains three integers: N (1 ≤ N ≤ 1000), K (1 ≤ K ≤ 1000) and S (0 ≤ S ≤ 15000).

Output

For each case print the case number and the result modulo 100000007.
Input                                                                                 
5                               
1 6 3
Case 1: 1

2 9 8   

Case 2: 7

500 6 1000

Case 3: 57286574

800 800 10000 

Case 4: 72413502


2 100 10

Case 5: 9    


First of all let us observe few things

(1)  The normal approach is to memoize it using dp[position][sum] and at that position try to fit all the values from 1 to K and recursively call the function. This gives us a solution on 0(n*s*k) somplexity, which is not sufficeient to pass.

Now we can observe that suppose we want the sum at position p to be 
SUM then what all values the i-1 th dice have as sum i.e it can 
have all values from  sum-1 to sum-k obviously there are few cases 
where the sum cannot be less than 1 and the previous dies total sum has to be >=(diecount) till there. But the overall idea is for that we can maintain a prefix array whose sum we can query in o(1) time.
A normal 2d array showed memory limit hence it was optimised to 1d array.



               
See the code for detailed implementation                                                     
                            
               ****** My code goes here**************

#include<bits/stdc++.h>
using namespace std;
long long int  dp[15100];
#define mod 100000007
int n,k,s;
long long int pre[15100];
int main()
{
   int t;
   cin>>t;
   int tt=1;
   while(t--)
   {
              memset(dp,0,sizeof(dp));   
      scanf("%d %d %d",&n,&k,&s);
     //  cout<<"called "<<endl;
          for(int i=1;i<=k;i++)
          dp[i]=1;
         memset(pre,0,sizeof(pre));
          for(int i=1;i<=k;i++)
          {
              pre[i]=pre[i-1];
pre[i]+=dp[i];
// if(pre[i]>=mod)
// pre[i]%=mod;
  }
 // cout<<"pre "<<endl;
// for(int i=1;i<=k;i++)
// cout<<pre[i]<<" ";
  for(int dice=2;dice<=n;dice++)
  {
  // cout<<"dice "<<dice<<endl;
          for(int sum=dice;sum<=min(dice*k,s);sum++)
          {
           
            int right=min(sum-1,(dice-1)*k);
            int left=max(dice-1,sum-k);
  //          cout<<"sum "<<sum<<" l r "<<left<<" "<<right<<endl;
  dp[sum]=(pre[right]-pre[left-1]+mod)%mod;
  //           cout<<"dp "<<dice<<" "<<sum<<" "<<dp[dice][sum]<<endl;
            //dp[dice][sum];
           // dp[dice][sum]%=mod;
          }
memset(pre,0,sizeof(pre));
for(int i=dice;i<=min(dice*k,s);i++)
{
   pre[i]=pre[i-1];
   pre[i]+=dp[i];
    if(pre[i]>=mod)
   pre[i]%=mod;
}
 
// cout<<endl;
  }
//  for(int i=6;i<=11;i++)
 /// cout<<dp[2][i]<<endl;
  
       cout<<"Case "<<tt<<": "<<dp[s]<<endl;
    tt++;
}
return 0;
}                                  

No comments:

Post a Comment