hdu4599Dice 概率dp+扩展欧几里得
Posted ljbguanli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu4599Dice 概率dp+扩展欧几里得相关的知识,希望对你有一定的参考价值。
//给一个正常的骰子
//F[n] 为这个骰子有一个数连续出现n次的期望
//h[n] 我这个骰子连续出现n个1的期望
//g[n] 为出现n个1的期望
//求最小的m1使得G(m1)>=F[n] , 最小的m2使得G(m2) >= H(n)
//f[i] 一个数连续掷了i次,其F[n]
//非常easy得到f[i] = 1 + 1/6*f[i+1] + 5/6*f[1] f[n] = 0
//easy求得F[n] = f[0] = (6^(n+1) - 6)/5
//h[i] 1连续出了i次其连续掷n次的期望
//h[i] = 1 + 1/6*h[i+1] + 5/6*h[0] h[n] = 0;
//H[n] = h[0] = (6^n-1)/5
//g[i] 为掷了i次1 的G[n]
//g[i] = 1/6*g[i] + 5/6*g[i+1] g[n] = 0 ;
//G[n] = g[0] = 6*n
//可得m1 >= (6^n - 1)/30 , m2 >= (6^n - 1)/5
//所以m1 = (6^n - 6)/30 + 1 , m2 = (6^n - 1)/5 ;
//因为须要对求余, 所以先用扩展欧几里得求出30和5的逆元
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std ;
const int mod = 2011 ;
typedef __int64 ll ;
ll prim(ll n)
{
ll c = 1;
ll a = 6 ;
while(n)
{
if(n&1)c = (c*a)%mod ;
a = (a*a)%mod ;
n/=2 ;
}
return c ;
}
ll exgcd(ll a , ll b , ll &x , ll &y)
{
if(b == 0)
{
x = 1;
y = 0;
return a ;
}
ll r = exgcd(b , a%b , x , y) ;
ll temp = x ;
x = y ;
y = temp - a/b*y ;
return r;
}
int main()
{
ll n ;
ll x1 , y ,x2;
exgcd(5 , mod ,x1,y) ;
exgcd(30 , mod ,x2,y) ;
while(x1<0)x1+=mod ;
while(x2<0)x2+=mod;
while(scanf("%I64d" ,&n)&&n)
{
ll m1 = (prim(n)*x1 - x1 + mod)%mod ;
ll m2 = (prim(n)*x2 - 6*x2 + 1 + mod)%mod ;
while(m2<0)m2+=mod ;
printf("%I64d %I64d\n" , m2 ,m1) ;
}
return 0 ;
}
//F[n] 为这个骰子有一个数连续出现n次的期望
//h[n] 我这个骰子连续出现n个1的期望
//g[n] 为出现n个1的期望
//求最小的m1使得G(m1)>=F[n] , 最小的m2使得G(m2) >= H(n)
//f[i] 一个数连续掷了i次,其F[n]
//非常easy得到f[i] = 1 + 1/6*f[i+1] + 5/6*f[1] f[n] = 0
//easy求得F[n] = f[0] = (6^(n+1) - 6)/5
//h[i] 1连续出了i次其连续掷n次的期望
//h[i] = 1 + 1/6*h[i+1] + 5/6*h[0] h[n] = 0;
//H[n] = h[0] = (6^n-1)/5
//g[i] 为掷了i次1 的G[n]
//g[i] = 1/6*g[i] + 5/6*g[i+1] g[n] = 0 ;
//G[n] = g[0] = 6*n
//可得m1 >= (6^n - 1)/30 , m2 >= (6^n - 1)/5
//所以m1 = (6^n - 6)/30 + 1 , m2 = (6^n - 1)/5 ;
//因为须要对求余, 所以先用扩展欧几里得求出30和5的逆元
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std ;
const int mod = 2011 ;
typedef __int64 ll ;
ll prim(ll n)
{
ll c = 1;
ll a = 6 ;
while(n)
{
if(n&1)c = (c*a)%mod ;
a = (a*a)%mod ;
n/=2 ;
}
return c ;
}
ll exgcd(ll a , ll b , ll &x , ll &y)
{
if(b == 0)
{
x = 1;
y = 0;
return a ;
}
ll r = exgcd(b , a%b , x , y) ;
ll temp = x ;
x = y ;
y = temp - a/b*y ;
return r;
}
int main()
{
ll n ;
ll x1 , y ,x2;
exgcd(5 , mod ,x1,y) ;
exgcd(30 , mod ,x2,y) ;
while(x1<0)x1+=mod ;
while(x2<0)x2+=mod;
while(scanf("%I64d" ,&n)&&n)
{
ll m1 = (prim(n)*x1 - x1 + mod)%mod ;
ll m2 = (prim(n)*x2 - 6*x2 + 1 + mod)%mod ;
while(m2<0)m2+=mod ;
printf("%I64d %I64d\n" , m2 ,m1) ;
}
return 0 ;
}
以上是关于hdu4599Dice 概率dp+扩展欧几里得的主要内容,如果未能解决你的问题,请参考以下文章
hdu 4586 Play the Dice (概率+等比数列)