在HUST上开了个比赛,加了几道刘汝佳书里的简单数学题。

Uva今天我这上不去,诶,还是老样子没变么,时不时抽风。HUST那里交了题也返回Judging Error 1 

也罢,先把这题解写了。


题目

这题给了个公式 ai = (ai–1 + ai+1)/2 – ci  (1<=i<=n). a是a0, a1,…, an+1 (n <= 3000; -1000 <=  ai 1000) 有n+2个元素的序列。给你a0, an+1, c1, ... , c要你求出 a1

推导:

先按将按公式可以得到的n个式子叠加,得到 a[1]+a[n] = a[0]+a[n+1]-2(c[1]+....+c[n]) ,变换为a[0]-a[1]-2(c[1]+...+c[n]) = a[n]-a[n+1]。所以我们可以将任何a[k]-a[k+1]表示为a[0]-a[1]了(因为 c 都已知)。再进行一次叠加,这次式子的左边为 (a[0]-a[1])+(a[1]-a[2])+...(a[n]-a[n+1]) = a[0]-a[n+1],右边都用a[0]-a[1]来表示,右边为 (a[0]-a[1])+(a[0]-a[1]-2sigma(c[k], k=1~1))+... = (n+1)a[0] - (n+1)a[1] - 2(sigma(c[1~1])+sigma(c[1~2])+...+sigma(c[1~n])). 这样,sigma部分内容只要采用迭代叠加c数组就行了,化简可得a[0]、a[n+1]求得a[1]的公式。

所以思路就是叠加式子,构造等式两边的相消跟式子与式子间的相消。


代码(ac):

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

#define MAXN 3002
double c[MAXN];
int n;

double solve(double a0, double an1)
{
    double t = 0;
    for(int i=1; i<=n; i++)
    {
        c[i] += c[i-1];
        t += c[i];
    }
    double ret = n*a0 + an1 - 2*t;
    return ret/(double)(n+1);
}

int main()
{
    int t;  scanf("%d", &t);
    while(t--)
    {
        double a0, an1;
        scanf("%d", &n);
        scanf("%lf%lf", &a0, &an1);
        for(int i=1; i<=n; i++)
        {
            scanf("%lf", &c[i]);
        }
        double ans = solve(a0, an1);
        printf("%.2lf\n", ans);
        if(t) printf("\n");
    }
}