UVa 10883 Supermean 题解
题目大意
超级平均数,即平均数的平均数。假定有一个数列
题目思路
最烂的方式即模拟算法,复杂度
我们可以手动模拟一下
那么系数就是二项式定理给出的三角形
无疑。
那么,我们就可以改写
计算它所需的时间是
使得组合数与
这是因为,
\binom{n}{m}=\frac{n!}{m!(n-m)!}=\frac{(m+1)\times(m+2)\times\cdots\times n}{1\times2\times3\times\cdots\times (n-m)} \binom{n}{m+1}=\frac{n!}{(m+1)!(n-m-1)!}=\frac{(m+2)\times\cdots\times n}{1\times2\times3\times\cdots\times (n-m-1)} 这样,我们就可以用手推导出它们的比值
\binom{n}{m+1}\left/\binom{n}{m}=\frac{n-m}{m+1}\right.
不幸的是由于
参考了几篇题解,他们使用了对数作为提高精度的工具。这里采用符号
那么我们就可以改写原来的式子:
虽然式子很长,但是它使用了对数来保证精度。
当然,随着我们使用对数,我们也得把增长贼快的二项式系数改作如下形式:
那么我们就可以只计算
代码如下。
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
long double sgn(long double x){
if(x>0) return 1.0;
if(x<0) return -1.0;
return 0.0;
}
void maintain(int __){
int n;
long double a[50010],ans=0.0,lbinom=0.0;
cin>>n,n--;
for(int i=0;i<=n;i++) cin>>a[i];
for(int i=0;i<=n;i++){
ans+=sgn(a[i])*pow(2.0,lbinom+log2(fabs(a[i]))-n);
// binom*=(n-i),binom/=(i+1);
lbinom+=log2((double)(n-i)/(double)(i+1));
}
// cout<<endl;
cout<<"Case #"<<__<<": "<<fixed<<setprecision(3)<<ans<<endl;
}
int main(){
int t,_=0;
cin>>t;
while(t--) maintain(++_);
return 0;
}
EOF