码迷,mamicode.com
首页 > 其他好文 > 详细

【tyvj P4879】骰子游戏

时间:2017-09-27 21:53:57      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:stream   span   计数   http   blank   with   mes   blog   ons   

http://www.tyvj.cn/p/4879

首先,投一个骰子,每个数字出现的概率都是一样的。也就是不算小A的话,n个人投出x个骰子需要的次数和点数无关。

计数问题考虑dp,令f(i,j)为前i个人投j个同点数的骰子的方案数,容易得f(i,j)=sum{f(i-1,j-k)*f(1,k) | 0<=k<=m}.

边界是f(1,j),具体是什么值呢?一个人投m个骰子,会得到6种点数,其中一种有j个,其他的五种有m-j个。也就是把m-j个骰子分成5份的方案数。

用插板法可得f(1,j)=C(m-j+4,4)=(m-j+1)(m-j+2)(m-j+3)(m-j+4)/24.

然后好像说这玩意可以用FFT优化,真成NOI Plus模拟赛了……

#include <iostream>
#define maxn 405
using namespace std;
typedef unsigned long long ullint;
const ullint c=998244353;
int n,m,x,y;
ullint dp[maxn][maxn*maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m>>x>>y;
    int cnt=0,tmp;
    for(int i=1;i<=m;i++)
    {
        cin>>tmp;
        if(tmp==y)
            cnt++;
    }
    
    for(int j=0;j<=m;j++)
        dp[1][j]=(m-j+1)%c*(m-j+2)%c*(m-j+3)%c*(m-j+4)%c*291154603%c;
    for(int i=2;i<=n;i++)
        for(int j=0;j<=i*m;j++)
            for(int k=0;k<=min(j,m);k++)
                dp[i][j]=(dp[i][j]+dp[i-1][j-k]*dp[1][k]%c)%c;
    ullint ans=0;
    for(int j=x-cnt;j<=n*m;j++)
        ans=(ans+dp[n][j])%c;
    cout<<ans<<endl;
    return 0;
}

 

【tyvj P4879】骰子游戏

标签:stream   span   计数   http   blank   with   mes   blog   ons   

原文地址:http://www.cnblogs.com/ssttkkl/p/7603852.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!