F - Flipping El-fetiera Gym - 101991F 概率 思維
阿新 • • 發佈:2018-12-11
題目連結:http://codeforces.com/gym/101991/problem/F
題意:
給你n*n的格子,每個格子是0或者1,現在要你取k個子矩陣,每次將這個矩陣中的0變為1,1變為0,那麼問k次操作之後你這n*n個數和的期望是多少。
做法:
先看這個面為1還是0,算出這個格子可能會被抽到的可能性,然後再用組合數和i次方表示取這k次的中能把它翻到1的可能性,加到答案中。具體看程式碼吧。。不知道怎麼形容。
#include<bits/stdc++.h> using namespace std; typedef long double ld; ld C[305][305]; int n,mp[305][305]; ld quick(ld a,int m){ ld ans=1; while(m){ if(m&1) ans=a*ans; a=a*a; m/=2; } return ans; } ld Calsum(int x,int y){ return (ld)x*(n-x+1)*y*(n-y+1); } ld Calbo(int n){ return (ld)(n*(1+n)/2); } void init(){ for(int i=0;i<=300;i++){ C[i][0]=1,C[i][1]=i; } for(int i=2;i<=300;i++){ for(int j=1;j<=i;j++){ C[i][j]=C[i-1][j]+C[i-1][j-1]; } } } int main(){ freopen("fetiera.in","r",stdin); init(); int t,k; cin>>t; while(t--){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&mp[i][j]); ld ans=0; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ ld tops=Calsum(i,j); ld a = tops/(ld)(Calbo(n)*Calbo(n)),add=0; if(mp[i][j]==0){ for(int i=1;i<=k;i+=2){ add+=C[k][i]*quick(a,i)*quick(1-a,k-i); } ans+=add; } else { for(int i=0;i<=k;i+=2){ //cout<<quick(a,k-i)<<endl; add+=C[k][i]*quick(a,i)*quick(1-a,k-i); } ans+=add; } } } printf("%.5Lf\n",ans); } return 0; }