uva10883 - Supermean 杨辉三角

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
#include
#include
#include
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;
}


你可能感兴趣的:(数学)