Coin 2017icpc-西安賽區 牛頓二項式

https://nanti.jisuanke.com/t/17115

題意:有一枚不均勻的硬幣,正面朝上的概率是q/p。現在拋k次硬幣,求其中有偶數次正面朝上的概率爲X/Y,現在要求輸出X*(Y對於1e9+7的逆元)。

題解:

for(int i=0;i<=k;i+=2){
	ans+=C(k,i)*(1-q/p)^(k-i)*(q/p)^i;
}

可以看出這是一個牛頓二項式,但是求的是偶數項。

根據牛頓二項式有:

偶數項+奇數項=(a+b)^k=1

偶數項-奇數項=(a-b)^k=(1-2*q/p)^k

所以偶數項=(1+(1-2*q/p)^k)/2

其中要求逆元

代碼:

#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<bitset>

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>

#include<iomanip>
#include<iostream>

#define debug cout<<"aaa"<<endl
#define d(a) cout<<a<<endl
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define MIN_INT (-2147483647-1)
#define MAX_INT 2147483647
#define MAX_LL 9223372036854775807i64
#define MIN_LL (-9223372036854775807i64-1)
using namespace std;

const int N = 100000 + 5;
const LL mod = 1000000000 + 7;
const double eps = 1e-8;

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 t=x;
	x=y;
	y=t-a/b*y;
	return r;
} 

LL quick(LL a,LL b){
	LL ans=1;
	a%=mod;
	while(b){
		if(b&1)
			ans=(ans*a)%mod;
		a=(a*a)%mod;
		b>>=1;
	}
	ans%=mod;
	return (ans+mod)%mod;
} 

int main(){
	int t;
	LL p,q,k,temp,x,y,ans;
	scanf("%d",&t);
	while(t--){
		scanf("%lld%lld%lld",&p,&q,&k);
		temp=quick(p,k);
		exgcd(temp,mod,x,y);
		ans=(quick(p-2*q,k)*x)%mod;
		ans=1+ans;
		exgcd(2,mod,x,y);
		ans=(ans*x)%mod;
		ans=(ans+mod)%mod;
		printf("%lld\n",ans);
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章