题解
难度:中等难度
知识点:递推 数学逻辑
思路:
本题考察递推公式,
1.本题将n无聊,m为不无聊。总共人数为s=n+m。每次从其中随机选出2个,将这两个数中的不无聊变成无聊,最终将s个人全部变成无聊。
2.假设当S个人中有K个人是不无聊,设平均需要f(K)次操作使得S个人全部变为无聊。每一次操作存在3种可能性:
K个不无聊的人都没有被选中,任然存在K个人处于不无聊。概率为:C(s - k, 2)/C(s, 2)
K个不无聊的人中选中了一个,此步后存在K-1个人处于不无聊。概率为:(s - k) * k / C(s, 2)
K个不无聊的人种选中了2个人,此步后存在K-2个人处于不无聊。概率为: C(k, 2)/C(s, 2)
因此:f(k) = 1 + C(s - k, 2) / C(s, 2) f(k) + (s - k) k / C(s, 2) )f(k - 1 )+ C(k, 2) / C(s, 2) f(k - 2)
【注】其中的1为该步骤需要付出的时间
由于f(0)=0;
由此:f(1):带入上述公式可得:f(1)-[(s-2)/s]f(1)=1 即:f(1)=s/2;
采用递推方式进行:
1.首先f0=0,f1=s/2;
采用for循环 利用公式:f(k) = 1 + C(s - k, 2) / C(s, 2) f(k) + (s - k) k / C(s, 2) )f(k - 1 )+ C(k, 2) / C(s, 2) f(k - 2) ,其中cur表示f(k),f(k-1)=f1,f(k - 2)=f0。
当计算出cur后,f0=f1,f1=cur。
###四舍五入保留一位小数:
例:保留五位小数:
#include <iostream> #include <iomanip> using namespace std; int main(){ float a; cin>>a; cout<<fixed<<setprecision(5)<<a; }
本题完整代码
#include<iostream> #include <iomanip> using namespace std; int main(){ int n,m; cin>>n>>m; int s=n+m; double f0=0,f1=s/2.0; for(int k=2;k<=m;k++){ double cur = s * (s - 1) / (1.0 * k * (2 * s - k - 1)) + 2 * (s - k) * 1.0 / (2 * s - k - 1) * f1 + (k - 1) * 1.0 / (2 * s - k - 1) * f0; f0 = f1; f1 = cur; } cout<<fixed<<setprecision(1)<<f1<<endl; return 0; }