腾讯2019技术岗笔试 猜硬币 众所周知,每一枚硬币都有两面,假定投掷一枚硬币,得到正面和反面的概率是一样的。小Q有一天和好朋友在玩投掷硬币的游戏,他投了n枚硬币,已知至少有p正,q反,求n枚硬币

众所周知,每一枚硬币都有两面,假定投掷一枚硬币,得到正面和反面的概率是一样的。小Q有一天和好朋友在玩投掷硬币的游戏,他投了n枚硬币,已知至少有p正,q反,求n枚硬币正面向上的期望是多少。
在这里插入图片描述
在这里插入图片描述

分析:
1.根据样例,分数取模的公式为:

其中4是期望的分子,3是期望的分母
    printf("%d\n",(4%1000000007+1000000007)/3);

原理:

https://www.cnblogs.com/dear_diary/p/10835168.html
下面是“分数”模运算的定义:
b, m互质
k = a/b (mod m) <=> kb = a (mod m)
这里求 x = 1/17 (mod 2668)
<=>17x = 1 (mod 2668)
<=>17x = 2668k + 1 (k∈整数)
取合适的k使得17|(2668k+1)
这里刚好17 | (2668 + 1)
所以k = 1, x = (2668+1)/17 = 157
当然,当k = 1 + 17n 时,
x = (2668 + 17·n·2668 + 1)/17 = 157 + 2668n
也符合条件(n任意整数)
但如果限定 2668 > x > 0,x是唯一的。

2.计算期望
(1)首先要计算多少情况,
比如:3 1 0时,由于硬币根据题意是不相同的,存在排列数。

正最少1个 负最少0个 种类数
1 2 C31=3 从3个里选出一个为正,剩下的是反
2 1 C32=3 从3个里选出2个为正
3 0 C33=1 从3个里选出3个为正

所以有1+3+3=7种,
计算期望:
(1/7*1)* C31+(1/7*2) *C32+(1/7*3)*C33=9/7

比如:2 1 0时,由于硬币根据题意是不相同的,存在排列数。

正最少1个 负最少0个 种类数
1 1 C21=2 从2个里选出一个为正,剩下的是反
2 0 C22=1 从2个里选出2个为正

有3种
计算期望:
(1/3*1)*C21+1/3*2 = 4/3

这样一来就很简单了,按照上面的思路写代码:

#include <stdio.h>
#include <stdlib.h>

/**
* 计算n!
**/
int CalcuNum(int num){
    int i=1;
    int calcu=1;
    do
    {
        calcu*=i;
        i++;
    }
    while(i<=num);
    //printf("%d n!=%d\n",num,calcu);
        return calcu;
}

/**
* 计算排列数Cin,i=up,n=num
*/
int CalcuCn(int up,int num){
    return CalcuNum(num)/(CalcuNum(up)*CalcuNum(num-up));
}


int main()
{
    int num=0;
    int pos=0;
    int neg=0;
    scanf("%d %d %d",&num,&pos,&neg);
    int i=pos;
    int category=0;
    int exceptup=0;
    for(i=pos;i<=num-neg;i++){
        //计算种类数
        int cn=CalcuCn(i,num);
        category+=cn;
        printf("%d个正, %d个反,有%d种,累计%d种\n",i,num-i,cn,category);
        //计算期望的分子
        exceptup+=cn*i;
    }
    //期望=期望的分子/排列种类数目
    printf("求模得到:\n");
    printf("%d\n",(exceptup%1000000007+1000000007)/category);
    return 0;
}

发布了140 篇原创文章 · 获赞 114 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/qinglingLS/article/details/100580434