F - Flipping El-fetiera Gym - 101991F 概率 思维

版权声明:本博客内容基本为原创,如有问题欢迎联系,转载请注明出处 https://blog.csdn.net/qq_41955236/article/details/84452495

题目链接: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;
}

猜你喜欢

转载自blog.csdn.net/qq_41955236/article/details/84452495