G - Gnoll Hypothesis Kattis - gnollhypothesis

题目链接
题目讲解先看另一位博主的讲解吧,我是看的他的博客比这写出来的这道题:
博客链接
求第一个位置时,选中有1的方案及相应的概率:
1-36% 2-25% 3-39%
1-24% 2-25% 4-51%
1-1% 2-25% 5-74%
1-24% 3-64% 4-12%
1-1% 3-64% 5-35%
1-1% 4-76% 5-23%
1号位置的概率期望为(36+24+1+24+1+1)/C(5,3) = 8.7
对于每一个位置i,f[i][j]表示第i个位置被选中,且其上面恰好有j个相邻的位置没有被选中时,i在k个位置中被选中的概率。f[i][j] = f[i-1][j-1]+a[i]。
当i上有j个位置未被选中时,第i、i-j-1位置已被固定,所以这样的情况一共有C(n-j-2,k-2)种。
对于每个i枚举每个j,答案累加C(n-j-2,k-2)f[i][j]/C(n,k)。
k=1时要特殊处理。每个位置答案均为1/n。
这道题目后来看完之后一点一点搞懂啦
先是我们需要一个500
500的c几几的答案图,这个直接调用就非常方便
在这里插入图片描述
可以看出啦这就是一个杨辉三角,也就是符合我们想要的c几几的答案矩阵表。
然后另一个是f矩阵:这个矩阵也是对应存储第i个被选中,而且刚好上面有j个空间的概率需要降下来加在一起的整个概率和。
这个也要看一下图才能真正知道却是这样存却是对啦。在这里插入图片描述
然后这个题目就是代码编辑:::当i上有j个位置未被选中时,第i、i-j-1位置已被固定,所以这样的情况一共有C(n-j-2,k-2)种。
对于每个i枚举每个j,答案累加C(n-j-2,k-2)*f[i][j]/C(n,k)。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <math.h>
#include <string>
#include <vector>
#include <map>
using namespace std;
#define esp 1e-5
const int N=520;
#define rep(i,start,endd) for(i=start;i<=endd;i++)
int n,k;
double a[N],c[N][N],f[N][N];//用来存储c几几得到的数字大小;
//f数组用来存储概率
void init(){
    c[0][0]=1.0;
    for(int i=1;i<505;i++){
        c[i][0]=c[i][i]=1.0;// 这个俩地方是每一行的开头和结尾,都不是下面那个式子求出来的。
        //这个c数组求完是个杨辉三角。所以这样求。。。。嗯~~~;
        for(int j=1;j<=i-1;j++){
            c[i][j]=c[i-1][j-1]+c[i-1][j];
        }
    }
    //刚刚求的是c几几的网格表
    for(int i=1;i<=n;i++){//这个边界n-1和n都行
        f[1][i]=f[1][i-1]+a[n-i+1];
    }
     for(int i=2;i<=n;i++){//注意边界!
            for(int j=1;j<=n;j++)//注意边界这个j的边界也是一样n和n-1都行

            f[i][j]=f[i-1][j-1]+a[i];
        }
    //这里就是求的是概率表格(在i被选中之后,上面有着连续的j的没有被选的概率之和。)
}
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++){
            cin>>a[i];
        f[i][0]=a[i];
    }
    if(k==1){//选谁都能连起来。所以是一百;;;
        for(int i=1;i<=n;i++){
            if(i!=1)printf(" ");
            printf("%.10f",100.0/(1.0*n));
        }
        puts("");
        return 0;//别忘啦加我就是这里没错啦好几遍。
    }
    init();
    for(int i=1;i<=n;i++){
        double ans=0.0;
        for(int p=0;p<=n-k;p++)//只能有n-k个空格来用做j
        {
            ans+=c[n-p-2][k-2]*f[i][p];
        }
        if(i!=1)printf(" ");
        printf("%.10f",ans/c[n][k]);
    }
    puts("");
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值