题目描述
Description
桌面上有 (2) 只完全相同的骰子,定义一次操作如下:将桌子上的骰子全部抛出,然后去掉那些奇数点的骰子,如果桌子上还有骰子,则重复上面的操作。
求操作 (n) 次后,桌面上至少还有一个骰子的概率。
为了方便起见,你只需要输出概率对 (19260817) 取模的结果。
Input
(1) 行 (1) 个整数 (n)
保证 (n) 在 (long) (long) 范围内
Output
(1) 行 (1) 个结果 对 (19260817) 取模的结果
Sample Input
1
Sample Output
4815205
HINT
对于 (40) (\%) 的数据 : (1leq nleq 1,000,000)
对于 (100) (\%) 的数据 : (n) 在 (long) (long) 范围内
第一次扔骰子,有 (frac{3}{4}) 概率至少还有一个骰子。
写在前面
骰(tóu)子
思路
很明显这道题就是要分析一个概率,最后再乘法逆元求模数
乘法逆元求模数比较简单,难点就在于求概率
首先我们先分析一下样例,样例抛了(1)次骰子,至少剩下一个骰子的概率为(frac{3}{4})
接下来我们来画个表来分析一下样例
情况 | A骰子 | B骰子 | 出现概率 | 剩余骰子数量 | 是否满足条件 |
---|---|---|---|---|---|
1 | 奇数 | 偶数 | (frac{1}{4}) | (1) | √ |
2 | 偶数 | 奇数 | (frac{1}{4}) | (1) | √ |
3 | 偶数 | 偶数 | (frac{1}{4}) | (2) | √ |
4 | 奇数 | 奇数 | (frac{1}{4}) | (0) | × |
所以说,总的出现概率就是(frac{1}{4}+frac{1}{4}+frac{1}{4}=frac{3}{4})
第二次投骰子时,情况如下
上次情况 | 本次情况 | A骰子 | B骰子 | 出现概率 | 剩余骰子数量 | 是否满足条件 |
---|---|---|---|---|---|---|
1 | 1 | 无 | 偶数 | (frac{1}{4} imesfrac{1}{2}=frac{1}{8}) | (1) | √ |
1 | 2 | 无 | 奇数 | (frac{1}{4} imesfrac{1}{2}=frac{1}{8}) | (0) | × |
2 | 3 | 偶数 | 无 | (frac{1}{4} imesfrac{1}{2}=frac{1}{8}) | (1) | √ |
2 | 4 | 奇数 | 无 | (frac{1}{4} imesfrac{1}{2}=frac{1}{8}) | (0) | × |
3 | 5 | 奇数 | 偶数 | (frac{1}{4} imesfrac{1}{4}=frac{1}{16}) | (1) | √ |
3 | 6 | 偶数 | 奇数 | (frac{1}{4} imesfrac{1}{4}=frac{1}{16}) | (1) | √ |
3 | 7 | 偶数 | 偶数 | (frac{1}{4} imesfrac{1}{4}=frac{1}{16}) | (2) | √ |
3 | 8 | 奇数 | 奇数 | (frac{1}{4} imesfrac{1}{4}=frac{1}{16}) | (0) | × |
4 | 9 | 无 | 无 | (frac{1}{4} imesfrac{1}{1}=frac{1}{4}) | (0) | × |
所以说,总的出现概率就是(frac{1}{8}+frac{1}{8}+frac{1}{16}+frac{1}{16}+frac{1}{16}=frac{7}{16})
发现什么规律了吗?
我们发现,对于每种状态来说,它下一次所发生的状态与本次发生状态是相同的,如下图:
图中每一个节点就代表一种情况(白色节点代表桌面上至少还有一个骰子)
那么每一个节点出现的概率如下图(图中出现的节点均为至少剩余一个骰子的情况):
那么桌面上至少还有一个骰子的总概率为
即
已知
所以
即
为
即
即
最终的结果就是(frac{2^{n+1}-1}{2^{2n}})对(19260817)取模的值
只要再用快速幂+逆元就可以了
代码
最后附上代码
#include<iostream>
#define mod 19260817
using namespace std;
unsigned long long n;
int p(unsigned long long x){//快速幂
int res=1;
long long c=2;
while(x>0){
if(x&1)res=(res*c)%mod;
c=(c*c)%mod;
x>>=1;
}
return res;
}
long long x,y;//逆元
void exgcd(int a,int b){
if(b==0){
x=1,y=0;
return;
}
exgcd(b,a%b);
x=x-(a/b)*y;
swap(x,y);
}
int main() {
cin>>n;
int a=p(n+1)-1,b=p(n*2);
exgcd(b,mod);
x=(x%mod+mod)%mod;
cout<<(a*x)%mod;
return 0;
}