2017 ACM-ICPC 亚洲区(西安赛区)网络赛 Coin 矩阵快速幂
Bob has a not even coin, every time he tosses the coin, the probability that the coin's front face up is \frac{q}{p}(\frac{q}{p} \le \frac{1}{2})pq(pq≤21).
The question is, when Bob tosses the coin kktimes, what's the probability that the frequency of the coin facing up is even number.
If the answer is \frac{X}{Y}YX, because the answer could be extremely large, you only need to print (X * Y^{-1}) \mod (10^9+7)(X∗Y−1)mod(109+7).
Input Format
First line an integer TT, indicates the number of test cases (T \le 100T≤100).
Then Each line has 33 integer p,q,k(1\le p,q,k \le 10^7)p,q,k(1≤p,q,k≤107) indicates the i-th test case.
Output Format
For each test case, print an integer in a single line indicates the answer.
样例输入
2 2 1 1 3 1 2
样例输出
500000004 555555560
题意:给定n,m,k,每次抛一个硬币为正面朝上的概率为(m/n),求抛k次硬币之后,硬币朝上的概率为多少(这里输出的是逆元之后的结果,所以很大)
题解:我们把概率转换为事件,一共n^k次事件,我们每扔一次硬币就可以看作有n次操作,m次为硬币朝上,n-m次硬币朝下。
我们设b(n)为抛n次硬币之后,硬币朝上次数为奇数的操作次数;a(n)为抛k次硬币之后,硬币朝上次数为偶数的操作次数。那么有递推式子
b(n)=b(n-1) * (n-m)+ a(n-1) * m;
a(n)=a(n-1) * (n-m)+ b(n-1) * m;
这个构造矩阵就容易多了
ac代码:
#include <cstdio> #include <iostream> using namespace std; typedef long long ll; const ll mod=1e9+7; struct Martix { ll mp[5][5]; int r,c; }; ll exgcd(ll a,ll b,ll &x,ll &y)// 扩展欧几里得 { if(b==0) { x=1; y=0; return a; } ll temp=exgcd(b,a%b,y,x); y-=(a/b)*x; return temp; } ll finv(ll a,ll m)// 求逆元 { ll x,y; ll g=exgcd(a,m,x,y); x=(x%m+m)%m;// return x; } long long quickmod(long long a,long long b,long long m) { long long ans = 1; while(b)//用一个循环从右到左便利b的所有二进制位 { if(b&1)//判断此时b[i]的二进制位是否为1 { ans = (ans*a)%m;//乘到结果上,这里a是a^(2^i)%m b--;//把该为变0 } b/=2; a = a*a%m; } return ans; } Martix mul(Martix a,Martix b) { int r=a.r; int c=b.c; Martix temp; temp.r=r; temp.c=c; for(int i=0;i<r;i++) { for(int j=0;j<c;j++) { temp.mp[i][j]=0; for(int k=0;k<r;k++) { temp.mp[i][j]=(a.mp[i][k]*b.mp[k][j]+temp.mp[i][j])%mod; } } } return temp; } ll n,m; ll pow(Martix a,ll k) { Martix ans; ans.r=2; ans.c=1; ans.mp[0][0]=n-m;// ans.mp[1][0]=m;// while(k) { if(k&1) ans=mul(a,ans); k/=2; a=mul(a,a); } return ans.mp[0][0]%mod; } int main() { int t; ll k; scanf("%d",&t); while(t--) { scanf("%lld %lld %lld",&n,&m,&k); ll y=quickmod(n,k,mod); Martix a; a.r=a.c=2; a.mp[0][0]=a.mp[1][1]=n-m; a.mp[0][1]=a.mp[1][0]=m; ll key=pow(a,k-1); //cout<<key<<endl; ll temp=key*finv(y,mod)%mod; cout<<temp<<endl; } return 0; }