组合数,对数。
这道题要用到20w的组合数,如果直接相乘的话,会丢失很多精度,所以用去对数的方式实现。
注意指数,因为取完一次后,还要再取一次才能发现取完,所以是(n+1)次方。
double 会爆掉,需要用long double
然后就是scanf和printf读入输出long doube会发生不可逆转的错误(dev-cpp),所以可以读入输出时候强制转换类型,或者用cin,cout(后者我感觉比较麻烦)。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> #include<iomanip> using namespace std; const int maxn = 200000; long double v1,v2,c; long double p,p1,p2,res; double pd,resd; int n,kase; long double f[maxn*2+10]; double logC(int n,int m) { return f[n]-f[m]-f[n-m]; } inline void init() { for(int i=1;i<=maxn*2;i++) f[i]=f[i-1]+log(i); } int main() { init(); /* while(scanf("%d",&n)==1) { scanf("%lf",&pd); p=pd; p1=p2=1; res=0; for(int i=1;i<=n;i++) { c=logC(2*n-i,n); v1=c+(n+1)*log(p)+(n-i)*log(1-p); v2=c+(n+1)*log(1-p)+(n-i)*log(p); res+=(double) i*(exp(v1)+exp(v2)); } resd=res; printf("Case %d: %.6lf ",++kase,resd); }*/ // 上面的代码是对的,嗯。我就想用cin,cout. while(cin>>n) { cin>>p; p1=p2=1; res=0; for(int i=1;i<=n;i++) { c=logC(2*n-i,n); v1=c+(n+1)*log(p)+(n-i)*log(1-p); v2=c+(n+1)*log(1-p)+(n-i)*log(p); res+=(double) i*(exp(v1)+exp(v2)); } cout << "Case "<<++kase<<": "; cout << setprecision(6) <<fixed<< res<<' '; } // 明显感觉还是 cstdio大法好。 return 0; }