B. 掷骰子
单点时限: 2.0 sec
内存限制: 512 MB
骰子,中国传统民间娱乐用来投掷的博具,早在战国时期就已经被发明。
现在给你 n 个骰子,求 n 个骰子掷出点数之和为 a 的概率是多少。
输入格式
第一行输入一个整数 T,表示有 T 组测试数据(1≤T≤10)
每组测试数据输入两个整数n,a,表示共有n个骰子,骰子点数总和为a(1≤n≤1000,n≤a≤6∗n)
输出格式
如题。答案对 109+7 取余。
样例
input
2 1 2 2 2
output
166666668 27777778
一个状态转移方程dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;// i指的是第i个筛子,j指的是当点数为j的时候的总方案(看了好久都没看懂,先记下来吧)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int mod=1e9+7; const int N=1e3+7; ll dp[N][N*6]; ll arr[N]; ll ksm(ll x,ll y){ ll res=1; while(y){ if(y&1) res=res*x%mod; x=x*x%mod; y>>=1; } return res; } int main(){ int t; scanf("%d",&t); while(t--){ int n,m; scanf("%d%d",&n,&m); memset(dp,0,sizeof(dp)); dp[0][0]=1; for(int i=1;i<=n;i++){ for(int j=i;j<=6*n;j++){ for(int k=j-6;k<j;k++){ if(k<0) continue; dp[i][j]=(dp[i][j]+dp[i-1][k])%mod; } } } printf("%lld\n",(dp[n][m]*ksm(ksm(6,n),mod-2))%mod); } return 0; }