题链:
http://www.lydsy.com/JudgeOnline/problem.php?id=1416
题解:
Pòlya瓦罐模型:
给定罐子里每种颜色的球的个数A[i],按题目要求随机操作若干次之后,摸到i号球的概率仍然为A[i]/sum(A[i])。
所以可以把题目看成若干次这种游戏,得出每次取球时的概率,然后更新对应的A[i]和sum(A[i])。
把每次的概率相乘即是答案。
要用到高精度,为了避免除法,可以先把分子分母质因数分解(最大质因子不超过20000),
把分子分母相同的因子相互抵消后,再用高精度乘起来。
代码:
#include<bits/stdc++.h> #define BIT 10000 #define MAXN 1005 using namespace std; struct Bigint{ int A[2*MAXN],len; Bigint(){memset(A,0,sizeof(A)); len=1;} void operator = (int rtm){ *this=Bigint(); do{ A[len++]=rtm%BIT; rtm/=BIT; }while(rtm); len--; } Bigint operator * (const Bigint &rtm) const{ static Bigint now; now=Bigint(); for(int i=1;i<=len;i++) for(int j=1;j<=rtm.len;j++){ now.A[i+j-1]+=A[i]*rtm.A[j]; now.A[i+j]+=now.A[i+j-1]/BIT; now.A[i+j-1]%=BIT; } now.len=len+rtm.len; while(!now.A[now.len]) now.len--; return now; } Bigint operator ^ (int b){ static Bigint now,base; base=*this; now=1; while(b){ if(b&1) now=now*base; b>>=1; base=base*base; } return now; } void Print(){ printf("%d",A[len]); for(int i=len-1;i;i--) printf("%04d",A[i]); } }; int T,N,D,S,pnt; int A[MAXN],prime[20005],cnt[2][20005]; void prework(){ static bool np[20005]; for(int i=2;i<=20000;i++) if(!np[i]){ prime[++pnt]=i; for(int j=i*i;j<=20;j+=i) np[j]=1; } } void Decomposition(int k,int val){ static int mincnt; if(val&&cnt[k][0]!=0) cnt[k][0]=1; else return (void)(cnt[k][0]=0); for(int i=1;i<=pnt&&val!=1;i++){ while(val%prime[i]==0) cnt[k][i]++,val/=prime[i]; mincnt=min(cnt[k][i],cnt[k^1][i]); cnt[k][i]-=mincnt; cnt[k^1][i]-=mincnt; } } Bigint combination(int k){ Bigint ret,tmp; ret=cnt[k][0]; for(int i=0;i<=pnt;i++) if(cnt[k][i]){ tmp=prime[i]; tmp=tmp^cnt[k][i]; ret=ret*tmp; } return ret; } int main(){ prework(); prime[0]=1; cnt[0][0]=cnt[1][0]=-1; scanf("%d%d%d",&T,&N,&D); for(int i=1;i<=T;i++) scanf("%d",&A[i]),S+=A[i]; for(int i=1,x,y;i<=N;i++){ scanf("%d%d",&x,&y); Decomposition(0,A[y]); Decomposition(1,S); A[y]+=D; S+=D; } Bigint a=combination(0); Bigint b=combination(1); if(!cnt[0][0]) b=1; a.Print(); putchar(‘/‘); b.Print(); putchar(‘\n‘); return 0; }