Problem B: Dice Dice Dice
Time Limit: 10 Sec
Memory Limit: 128 MB
Submit: 81
Solved: 17
[ Submit][ Status][ Web Board]
Description
There are 1111 ways in which five 6-sided dice (sides numbered 1 to 6) can be rolled so that the top three numbers sum to 15. Some examples are:
D1,D2,D3,D4,D5 = 4,3,6,3,5
D1,D2,D3,D4,D5 = 4,3,3,5,6
D1,D2,D3,D4,D5 = 3,3,3,6,6
D1,D2,D3,D4,D5 = 6,6,3,3,3
Now we have a extended problem:
In how many ways can n m-sided dice (sides numbered 1 to m) be rolled so that the top k numbers sum to p?
Input
There are multiple test cases. (about 15 groups)
For each test case, there is only four integers n, m, k, p. (1 <= k <= n <= 20, 3 <= m <= 12)
Output
For each test case, output an integer indicating the answer.
Sample Input
5 6 3 156 6 3 15
Sample Output
11117770
HINT
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
using namespace std;
#define LL long long
int n,m,k,p;
int re[109];
LL ans;
LL N(int t){
LL ret = 1;
for(int i=2;i<=t;i++)
ret*=i;
return ret;
}
void dfs(int t,int lim)
{
if(t<k){
for(int i=lim;i>0;i--)
{
re[t] = i;
dfs(t+1,i);
}
}else if(t==k){
int s = 0;
for(int i=0;i<k;i++)
s+=re[i];
if(s!=p) return ;
// for(int i=0;i<k;i++)
// cout<<re[i]<<" ";cout<<endl;
if(k<n)
for(int i=lim;i>0;i--)
{
re[t] = i;
dfs(t+1,i);
}
else
{
re[n]=lim;
dfs(t+1,lim);
}
return ;
}else if(t>k&&t<n)
{
for(int i=lim;i>0;i--)
{
re[t] = i;
dfs(t+1,i);
}
return ;
}
if(t>=n){
LL tmp = N(n);
// cout<<"con:"<<endl;
// for(int i=0;i<n;i++)
// cout<<re[i]<<" ";cout<<endl;
// cout<<tmp<<endl;
int c=1;
re[n] = -1;
for(int i=1;i<=n;i++)
{
if(re[i]!=re[i-1])
{
tmp/=N(c);
c=1;
}
else
c++;
}
ans+=tmp;
return ;
}
}
int main()
{
// freopen("in.txt","r",stdin);
while(~scanf("%d%d%d%d",&n,&m,&k,&p))
{
// cout<<"<<<<<<<<<<<"<<endl;
ans = 0;
dfs(0,m);
cout<<ans<<endl;
}
return 0;
}