欧拉项目 323题

题目链接

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

有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 来保存概率也能给出正确答案,我没有试,不确定。
下面是我的代码:

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
      
      
public class
{
public BigInteger Numerator { get; set; }
public BigInteger Denominator { get; set; }
public (BigInteger numerator, BigInteger denominator)
{
Numerator = numerator;
Denominator = denominator;
}
大专栏   欧拉项目 323题="line">}
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");
}

猜你喜欢

转载自www.cnblogs.com/lijianming180/p/12302572.html
今日推荐