Do you know how to compute the mean (or average) of n numbers?Well, that's not good enough for me. I want the supermean! "What's asupermean," you ask? I'll tell you. List the n given numbers innon-decreasing order. Now compute the average of each pair of adjacentnumbers. This will give you n - 1 numbers listedin non-decreasing order. Repeat this process on the new list of numbersuntil you are left with just one number - the supermean. I tried writinga program to do this, but it's too slow. :-( Can you help me?
Input
The first line of input gives the number of cases, N.N test cases follow. Each one starts with a line containingn (0<n<=50000). The next line will containthe n input numbers, each one between -1000 and 1000, in non-decreasingorder.
Output
For each test case, output one line containing "Case #x:" followed by the supermean, rounded to 3 fractional digits.
Sample Input | Sample Output |
4 1 10.4 2 1.0 2.2 3 1 2 3 5 1 2 3 4 5 | Case #1: 10.400 Case #2: 1.600 Case #3: 2.000 Case #4: 3.000 |
写出来是一个倒三角形,这个倒三角形也是N个正杨辉三角(分别以每个元素为顶点)的交叉,倒三角形最下面顶点的数相当于正杨辉三角第N行所有元素的和。
因此每个数的次数是杨辉三角第N行的系数,最后再除以2^(N-1)。
递推超时,因为只求一行,C(n,m)=C(n,m-1)*(n-m+1)/m,这里N很大,组合数太大,求组合数后除以2^(n-1)的结果不大。每一项可以表示成e^ln(C(N,i)*a[i]/2^(N-1))=e^(ln(C(N,i)+ln(a[i])-(N-1)*ln2)。lnC(N,i)=lnC(N,i-1)+ln(N-i+1)-ln(i),也就是不递推C(N,i),而递推lnC(N,i),在计算过程中以ln的形式把2^(N-1)除掉,最后在用exp算出结果。
注意正负问题。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int T,N;
int main(){
freopen("in.txt", "r", stdin);
int cas=0;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
N--;
double ans=0,pre=0,t;
scanf("%lf",&t);
if(t<0) ans-=exp(log(-t)-N*log(2));
else ans+=exp(log(t)-N*log(2));
for(int i=1;i<=N;i++){
pre+=log(N-i+1)-log(i);
scanf("%lf",&t);
if(t<0) ans-=exp(pre+log(-t)-N*log(2));
else ans+=exp(pre+log(t)-N*log(2));
}
printf("Case #%d: %.3lf\n",++cas,ans);
}
return 0;
}