標籤:limits rac for har stdio.h sum highlight length mit
題意:有$k$種蘋果和$n$個箱子,每個箱子中有一些蘋果,先等機率選取$n$個箱子組成集合的非空子集,再從選出的蘋果中隨機選一個,問每種蘋果被選中的機率是多少
設箱子$i$有$cnt_{i,j}$個第$j$種蘋果,第$i$個箱子的總蘋果數$siz_i=\sum\limits_{j=1}^kcnt_{i,j}$,蘋果總數$sum=\sum\limits_{i=1}^nsiz_i$
因為選完非空子集後,每個箱子中的蘋果被選中的機率是相同的,所以先考慮選箱子,設$f_{i,j}$表示在前$i$個箱子中選$j$個蘋果的方案數(只能一箱一箱選),那麼$f_{i,j}=f_{i-1,j}+f_{i-1,j-siz_i}$
再設$g_{i,j}$表示在所有不是$i$的箱子中選$j$個蘋果的方案數,那麼$g_{i,j}=f_{n,j}-g_{i,j-siz_i}$
於是,選中了箱子$i$的情況對箱子$i$中每個蘋果被選中的機率貢獻為$\frac1{2^n-1}\sum\limits_{j=0}^{sum-siz_i}\frac{g_{i,j}}{j+siz_i}$(枚舉箱子$i$外被選中的蘋果數)
#include<stdio.h>#include<vector>#include<string>#include<string.h>using namespace std;typedef double du;typedef long long ll;ll f[500010],g[500010];int cnt[60][60],siz[60],sum;class RandomApple{public:vector<du>theProbability(vector<string>hun,vector<string>ten,vector<string>one){int n,k,i,j;du t;n=hun.size();k=hun[0].length();for(i=0;i<n;i++){for(j=0;j<k;j++){cnt[i][j]=(hun[i][j]-‘0‘)*100+(ten[i][j]-‘0‘)*10+one[i][j]-‘0‘;siz[i]+=cnt[i][j];}sum+=siz[i];}vector<du>res(k,0);f[0]=1;for(i=0;i<n;i++){for(j=sum;j>=siz[i];j--)f[j]+=f[j-siz[i]];}for(i=0;i<n;i++){memset(g,0,sizeof(g));t=0;for(j=0;j<=sum;j++){g[j]=f[j]-(j>=siz[i]?g[j-siz[i]]:0);if(j+siz[i]<=sum)t+=g[j]/(du)((1ll<<n)-1)/(du)(j+siz[i]);}for(j=0;j<k;j++)res[j]+=t*cnt[i][j];}return res;}};/*int main(){RandomApple cl;vector<string>a,b,c;vector<du>res;char s[60];for(scanf("%s",s);s[0]!=‘-‘;scanf("%s",s))a.push_back(s);for(scanf("%s",s);s[0]!=‘-‘;scanf("%s",s))b.push_back(s);for(scanf("%s",s);s[0]!=‘-‘;scanf("%s",s))c.push_back(s);res=cl.theProbability(a,b,c);for(du t:res)printf("%.9lf ",t);}*/
[SRM478]RandomApple