標籤:數學
1828. Approximation by a ProgressionTime limit: 0.5 second
Memory limit: 64 MB
Your are given a sequence of integers
a1, …,
an. Find an arithmetic progression
b1, …,
bn for which the value ∑(
ai ?
bi)2 is minimal. The elements of the progression can be non-integral.InputThe first line contains the number
n of elements in the sequence (2 ≤
n ≤ 104). In the second line you are given the integers
a1, …,
an; their absolute values do not exceed 104.OutputOutput two numbers separated with a space: the first term of the required arithmetic progression and its difference, with an absolute or relative error of at most 10?6. It is guaranteed that the answer is unique for all input data.Samples
| input |
output |
40 6 10 15 |
0.400 4.900 |
4-2 -2 -2 -2 |
-2 0
|
題意 : 給定整數數組 ai。求一個等差數列bi。 等差數列bi要能使∑(
ai ?
bi)2 最小的。輸出 b1,d。兩者可以是小數。
做法:推公式比較麻煩。步驟如下:
為方便計算 設 第零為b0,方差為d。 那麼 bi=b0+i*d 。b1=b0+d。
然後帶入∑(
ai ?
bi)2
帶入 bi=b0+i*d 。得到∑(b0^2+(i*d)^2+2*b0*i*d-2*b0*ai-2*i*d*ai+ai^2)
把b0提出來 得到∑ (b0^2+b0*(2*i*d-2*ai)+(i*d)^2-2*i*d*ai+ai^2)
把d提出來 得到∑ ( i^2*d^2+d*(2*b0*i-2*i*ai)+b0^2-2*b0*ai+ai^2)
可以發現 兩個 分別關於 b0 和d 的二元一次函數都是開口向上的。所以極值落在 -b/2a上。
把∑化到括弧裡面。
設常數 c1 等於∑bi ,c2 =∑(i*bi) c3= ∑i c4=∑i^2 ∑中i都是從1到n的累加
最後可以化簡得到 b0的極值點 b0=-b/2a=(-d*c3+c1)/n,d的極值點 d==-b/2a=(-b0*c3+c2)/c4。這兩個二元一次方程。 兩個式子,可以解出 d =((c1*c3)/n-c2)/(c3*c3/n-c4) b0=(-d*c3+c1)/n
方程裡a1就是等於上面的b0.
#include <stdio.h>#include <stdlib.h>#include <string.h> #include <string>#include <iostream>#include <algorithm>using namespace std; #include <vector> int b[11000];int main(){double n;while(scanf("%lf",&n)!=EOF){for(int i=1;i<=n;i++){cin>>b[i];}//c1 bi hedouble c1=0;for(int i=1;i<=n;i++){c1+=b[i];}//c2 ibi hedouble c2=0;for(int i=1;i<=n;i++){c2+=b[i]*i;}//c3 i hedouble c3=0;for(int i=1;i<=n;i++){c3+=i;}//c4 i^2 hedouble c4=0;for(int i=1;i<=n;i++){c4+=i*i;}double d=1.0*((c1*c3)/n-c2)/((c3*c3)/n-c4);double a=1.0*(-d*c3+c1)/n;a+=d;if(d<0.000001&&d>-0.000001)d=0;printf("%lf %lf\n",a,d);}return 0;}
URAL 1828. Approximation by a Progression 數學