有n根鞋带混在一起,现在重复n次以下操作:随机抽出两个鞋带头,把它们绑在一起。可以想象,这n次之后將不再有单独的鞋带头,n条鞋带系成了一些环。那么有多大概率刚好所有这些鞋带只形成了一个环?
Input
仅一行,包含一个整数n (2<=n<=1000)。
Output
输出一行,为刚好成环的概率。
Input示例
2
Output示例
0.666667
首先放上网上的思路:
考虑p[i-1]已经计算好了,现在来了一条新鞋带,i,这个分之应该是2*(i-1),因为要再i-1根鞋带组成的环里插入一根鞋带,有i-1种插法,然后两头替换需要乘以2;
分母应该是2*i-1,同样两头连接不同鞋带2*(i-1)+1(自己连自己)
所以递推式:p[i]=2*(i-1)/(2*i-1)*p[i-1]; p[1]=1.0;
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
int n;
int fz = 1, fm = 1;
cin >> n;
double p = 1.0;
for(int i = 2; i <= n; i++)
p = p*(i*2-2)/(i*2-1);
printf("%.6f", p);
return 0;
}
我自己想出来的思路:
假设有n个鞋带,第一个鞋带的选择就是剩下2*(n-1)+1个选择(+1,是自己成一个圈),不成环的选择就是2*(n-1),一开始我在这个基础上*2了。。因为觉得当前这个鞋带每一头都有2*(n-1)个选择。。其实不是的,因为一个鞋带的一个头有两个选择,剩下那个头的选择也就确定了。。 比如 12,34,分别代表两个鞋带的两个头,13连在一起24就一起了,14连在一起23就一起了,你在练24根23就重复了,就算许多个鞋带也是这样的。。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
int n;
long long fz = 1, fm = 1;
cin >> n;
double ans = 1.0;
for(int i = 1; i <= n-1; i++)
ans = ans * ((2*n-2*i)*1.0/(2*(n-i)+1));
printf("%.6f\n", ans);
return 0;
}
总结显然网上的思路更好。。以后这种题目,可以多想想从之前的状态怎么得到。。我这样倒着想还是卡了几下的。。一般组合数dp都可以从前往后想,从小往大想把(做题少了啊,唉),记录有用的东西,他要成一个整环的概率,我们就只记录成一个整环的概率,前面已经是一整个环了,你要加一个给他,要么把这个绳子插入环中成为一个环,要么就自己成一个圈,然后乘以两者商就是这个绳子插进去成环的概率。。