您的位置:首页 > 其它

HDU 4599 Dice 2013 ACM-ICPC吉林通化全国邀请赛J题

2013-09-01 16:16 399 查看
转载自http://www.cnblogs.com/allh123/archive/2013/08/25/3281039.html

先推出F(n)的公式:

设dp[i]为已经投出连续i个相同的点数平均还要都多少次才能到达目标状态。则dp[0]就是F(n)

则有递推式dp[i] = 1/6*(1+dp[i+1]) + 5/6*(1+dp[1]).考虑当前这一次掷色子,有1/ 6的概率投的和前面的一样,有5/6的概率不一样,不一样就要重新投,就到了dp[1]的状态,这里投了一次,所以要加1.边界有dp[0] = dp[1]+1,dp
= 0;

H
应该是6*F


推出来的F(n) = (6^n-1)/5,H(n) = 6*(6^n-1)/5.G(m) = 6*m,平均投6次会出现一次1.

或者概率DP,设dp[i]表示已经投出i次1平均还要投多少次才能到达目标状态。

则有dp[i] = 1/6*(1+dp[i+1]) + 5/6*(1+dp[i]).

边界条件dp[m]=0。

然后就得到m1>=(6^n-1)/30,m2>=(6^n-1)/5.显然最小的m2 = (6^n-1)/5

而(6^n-1)%30 !=0,通过观察发现有6%30=6,6*6%30=6,那么就有6^n%30=6也就是说虽然6^n%30 !=0,但是6^n+24%30 == 0,且这就是m1,

即有m1 = (6^n+24)/30.....现在就是求m1%2011,m2%2011,我是用的先算6^n%2011,用快速幂,然后求出分别求出30和5对应2011的逆元。

至于求逆元,用扩展欧几里得算法即可·······甚至用电脑暴力算出也行



#include<cstdio>
const int mod = 2011;
const int e1 = 1944,e2 = 1609;//30,5的逆元
inline int qPow(int x,int p)
{
    int a=6,ans=1;
    while(x)
    {
        if(x&1) ans  = ans*a%p;
        a = a*a%p;
        x >>= 1;
    }
    return ans;
}
int main()
{
//    freopen("in.txt","r",stdin);
    int n,tmp,tmp1,tmp2,ans1,ans2;
    while(scanf("%d",&n),n)
    {
        tmp = qPow(n,mod);
        tmp1 = (tmp+24+mod)%mod;
        tmp2 = (tmp-1+mod)%mod;
        ans1 = tmp1*e1%mod;
        ans2 = tmp2*e2%mod;
        printf("%d %d\n",ans1,ans2);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐