欧拉项目 323题

僤鯓⒐⒋嵵緔 提交于 2020-02-13 11:01:25

题目链接

这道题乍一看是位运算,其实是一道和概率分布相关的题目。

有y0 y1 y2一系列32bits的无符号数
x初始为0,然后和这一系列数异或操作,操作了N次,直到x是2^32-1,其实就是x所有bits都是1。
求N的期望值。

期望怎么计算呢?
计算对于每一个n对应的概率p(n),然后加权求和。
我们现在逐一分析一下
N为1,那么说明y0每一个bits都是1,概率是1/(2^32)
N为2,针对每个bit进行计算,第一个bit,结果是1的概率是1减去不是1的概率,不是1的概率就是y0的第一bit不是0,y1的第一bit也不是0,概率是1/(2^2),那么p(2)=(1-1/(2^2))^32 - p(1)
N为3,p(3)=(1-1/(2^3))^32 - p(1) - p(2)
以此类推
题目要求小数点后十位,如果p(n)很小,乘以n对结果都没有影响了,也就是p(n)*n小于10的十次方。

我计算的时候搞了一个数据结构保存概率的分子和分母。我解答出来之后,看了下别人的分析,感觉直接使用double 来保存概率也能给出正确答案,我没有试,不确定。
下面是我的代码:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
public class {    public BigInteger Numerator { get; set; }    public BigInteger Denominator { get; set; }    public (BigInteger numerator, BigInteger denominator)    {        Numerator = numerator;        Denominator = denominator;    }}public static string GetAnswer(){    List<Probability> probabilities = new List<Probability>();    probabilities.Add(new Probability(0, 1));    BigInteger twoPow32 = BigInteger.Pow(2, 32);    for (int i = 1; ; i++)    {        BigInteger baseDenominator = BigInteger.Pow(2, i);        BigInteger baseNumerator = baseDenominator - 1;        BigInteger lastBaseDenominator = BigInteger.Pow(2, i - 1);        BigInteger lastBaseNumerator = lastBaseDenominator - 1;        BigInteger denominator = BigInteger.Pow(baseDenominator, 32);        BigInteger numerator = BigInteger.Pow(baseNumerator, 32);        BigInteger lastNumerator = BigInteger.Pow(lastBaseNumerator, 32);        probabilities.Add(new Probability(            numerator - lastNumerator * twoPow32,            denominator));        if (probabilities[i].Denominator / probabilities[i].Numerator / i > BigInteger.Pow(10, 12))        {            break;        }    }    BigInteger ansDenominator = probabilities.Last().Denominator;    BigInteger ansNumerator = 0;    for (int i = 1; i < probabilities.Count; i++)    {        Probability current = probabilities[i];        BigInteger times = ansDenominator / current.Denominator;        ansNumerator += times * current.Numerator * i;    }    BigInteger times11 = ansNumerator * 100000000000 / ansDenominator;    double answer = (double)times11 / 100000000000;    return answer.ToString("N10");}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!