题目大意
三个杯子,硬币一开始在中间的杯子里,每次操作可能是左边和中间或右边和中间交换,问n次操作后,硬币在中间的概率
思路
设
f(n)
是n次操作后硬币在中间的概率,则很明显,
f(n)=1−f(n−1)2
展开化简得到可以得到
anbn
的形式 易得
bn=2n−1
an=⎧⎩⎨⎪⎪⎪⎪2n−1+132n−1−13n为偶数,n为奇数
显然 2n−1+1 和 2n−1 互质,所以不用约分了,幂的操作可以用快速幂来处理,再用费马小定理转除为乘,这题就搞定了
PS:代码给了CPP和Python两个版本的。
PS2:原生的Python比较慢,PyPy快一点,CF上交PyPy就可以过,python大法好,自己处理大数,pow自带取模~~
代码
CPP
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn = 1e5+10;
const int mod = 1e9+7;
typedef long long ll;
ll num;
ll Qpow(ll a,ll b){
ll res = 1;
while(b){
if(b&1) res = res * a %mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
int main (){
int n;
cin >>n;
ll b = 2;
ll flag = -1;
for(int i = 0 ; i < n ; i ++){
scanf("%I64d",&num);
b = Qpow(b,num);
if(num %2 == 0) flag = 1;
}
b = b*Qpow(2LL,mod-2)%mod; // b = 2^n-1
ll a = (b+flag+mod)%mod*Qpow(3LL,mod-2)%mod; //a = (2^n-1 -/+ 1) / 3
printf("%I64d/%I64d",a,b);
return 0;
}
Python
from functools import reduce
mod = 1000000007
n = input()
num = list(map(int,input().split()))
flag = 1 if len(list(filter(lambda x: x%2 == 0,num))) else -1
b = reduce(lambda x,y:pow(x,y,mod),num,2)
b = b*pow(2,mod-2,mod)%mod # b = 2^n-1
a = (b+flag)*pow(3,mod-2,mod)%mod #a = (2^n-1 -/+ 1) / 3
print("%d/%d"%(a,b))