1. 程式人生 > >[NOI2006]神奇口袋

[NOI2006]神奇口袋

spl reg 提示 ons 如果 show ... post urn

題面在這裏

題意

開始時袋中有\(t\)種小球,第\(i\)種小球有\(t_i\)個,之後每次等概率取出一個球,第\(i\)次取球時觀察這個球的顏色\(c_i\)放回並向袋中加入\(d\)個顏色為\(c_i\)的球;
給出一組詢問\([x_i,y_i](1\le i\le n)\),求同時滿足第\(x_i\)次取球的顏色為\(y_i\)的概率

\(1≤t,n≤1000, 1≤a_k ,d≤10, 1≤x_1<x_2<…<x_n≤10000, 1≤y_k≤t\)

hint

有沒有註意到\(1≤x_1<x_2<…<x_n≤10000\)這個條件?
感覺又鬼畜又沒有用對麽?
那麽我們把這個條件刪掉


其實這個條件僅僅是在給你一個提示

sol

其實我做題的時候也不知道這個條件有什麽用...於是我就沒有做出來
如果\(x_i=i\)你還不會做?直接模擬即可

所以這道題直接模擬就可以了。
!!!!!!是的很震驚對吧
給你\(1≤x_1<x_2<…<x_n≤10000\)這個條件,
就是讓你考慮怎麽把這個條件化成\(x_i=i\)的......

接下來我們開始證明,
如果僅僅考慮一次抽取的情況,每次抽到顏色\(c\)的概率都是一樣的,
即第\(i\)次抽到顏色\(c\)的概率和第\(i+1\)次抽到顏色\(c\)的概率相同
設第\(i\)次抽之前,袋子裏有\(a\)個顏色為\(c\)的球,有\(tot\)

個顏色不為\(c\)的球
那麽第\(i\)次抽抽到\(c\)的概率顯然是\(P_i=\frac{a}{tot}\)
那麽第\(i+1\)次抽抽到\(c\)的概率呢?
\[P_{i+1}=\frac{a}{tot}\times\frac{a+d}{tot+d}+(1-\frac{a}{tot})\times\frac{a}{tot+d}=\frac{a}{tot}=P_i\]
嗯是的

於是直接把\([x_1,x_2,x_3,...,x_n]\)轉換為\([1,2,3,...,n]\)即可
註意高精(可以考慮先\(fact\),最後再化系數)

代碼

#include<bits/stdc++.h>
#include<algorithm> #include<iostream> #include<cstdlib> #include<iomanip> #include<cstring> #include<complex> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define mp make_pair #define pb push_back #define RG register #define il inline using namespace std; typedef unsigned long long ull; typedef vector<int>VI; typedef long long ll; typedef double dd; const dd eps=1e-10; const int mod=1e9+7; const int N=5010; const int M=20010; il ll read(){ RG ll data=0,w=1;RG char ch=getchar(); while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘))ch=getchar(); if(ch==‘-‘)w=-1,ch=getchar(); while(ch<=‘9‘&&ch>=‘0‘)data=data*10+ch-48,ch=getchar(); return data*w; } il void file(){ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); } int t,n,d,a[N],y[N],sum; int pri[M],vis[M]; il void sieve(){ vis[1]=1; for(RG int i=2;i<M;i++){ if(!vis[i])pri[++pri[0]]=i; for(RG int j=1;j<=pri[0]&&1ll*pri[j]*i<M;j++){ vis[i*pri[j]]=1;if(i%pri[j]==0)break; } } } int sys[3][M]; il void fact(int x,int id){ for(RG int j=1;j<=pri[0]&&1ll*pri[j]*pri[j]<=x;j++) while(x%pri[j]==0)sys[id][j]++,x/=pri[j]; for(RG int j=1;j<=pri[0]&&1ll*pri[j]<=x;j++){ while(x%pri[j]==0)sys[id][j]++,x/=pri[j];if(x==1)break; } } struct bignumber{ int ws,s[5005]; il void init(){ws=s[1]=1;} il void times(int x){ if(!ws)init(); for(RG int i=1;i<=ws;i++)s[i]*=x; for(RG int i=1;i<=ws;i++) if(s[i]>=10)s[i+1]+=s[i]/10,s[i]%=10; while(s[ws+1])ws++,s[ws+1]+=s[ws]/10,s[ws]%=10; } il void print(){ for(RG int i=ws;i;i--)printf("%d",s[i]); } }A[3]; il void solve(){ for(RG int i=1,minn;i<=pri[0];i++){ minn=min(sys[1][i],sys[2][i]); sys[1][i]-=minn;sys[2][i]-=minn; } A[1].init();A[2].init(); for(RG int id=1;id<=2;id++) for(RG int i=1;i<=pri[0];i++) for(RG int j=1;j<=sys[id][i];j++)A[id].times(pri[i]); A[2].print();printf("/");A[1].print();puts(""); } int main() { t=read();n=read();d=read();sieve(); for(RG int i=1;i<=t;i++)a[i]=read(),sum+=a[i]; for(RG int i=1;i<=n;i++) read(),y[i]=read(),fact(a[y[i]],2),a[y[i]]+=d,fact(sum,1),sum+=d; solve();return 0; }

[NOI2006]神奇口袋