该题如果用普通方法,精度损失太大,而且组合数也太大,难以求解。
但是如果用组合数公式,阶乘又太大,会溢出,所以我们可以采用取对数的方法,将组合数和取对数操作一起进行,然后用库函数exp()转换回来就行了。
细节参见代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 1000000000;
const int maxn = 100000*2 + 5;
int n,kase = 0;
double p;
long double logF[maxn*2];
void init() {
for(int i=1;i<2*maxn;i++) {
logF[i] = logF[i-1] + log(i);
}
}
long double logC(int n,int m) {
return logF[n] - logF[n-m] - logF[m];
}
int main() {
init();
while(~scanf("%d%lf",&n,&p)) {
double ans = 0;
for(int i=0;i<=n;i++) {
long double c = logC(2*n-i,n);
long double v1 = c + (n+1)*log(p) + (n-i)*log(1-p);
long double v2 = c + (n+1)*log(1-p) + (n-i)*log(p);
ans += (double)i*(exp(v1) + exp(v2));
}
printf("Case %d: %.6f\n",++kase,ans);
}
return 0;
}