[羅区P3338] ZJOI2014力

問題の説明

:Fjのように定義される所定のN個のQiは、以下与える
< - {J \ {Q_IのFRAC [F_J = \ sum_ {私は\ sum_ I} Jを} \ {FRAC Q_I Q_j} {(のIJ)^ 2}> \ q_j} {(IJ)^ 2
} \] 順Eiは=部屋/チー、EIが追求。

入力形式

最初の行の整数n。

次のn行はそれぞれi行目の気によって表される数値を入力します。

出力フォーマット

N行、第i番目の出力線En。

答えは1E-2の標準誤差があることができるより多くのではありません。

サンプル入力

5
4006373.885184
15375036.435759
1717456.469144
8514941.004912
1410681.345880

サンプル出力

-16838672.693
3439.793
7509018.566
4595686.886
10903040.872

解決

まず、式を簡略化するために最初に見える
[\} ALIGN =左開始\ {Eを[I] =&\ {F. FRAC [I] {P} [I]}&\\ = \ sum_ {J <{I} \ FRAC {P [J]}
{(IJ)^ 2}} - \のsum_ {J> I} {\ FRAC {P [J]} {(IJ)^ 2}} \端{\]}整列し、次いでセット\(F1 [I] = P [I]、G [I] = \ FRAC {1} {I ^ 2} \) 元の方程式を与えるために簡略化することができる:
\ [Eを[I] = \ sum_ {J = 1} ^ {I-1
} F1 [J] * G [IJ] - \ sum_ {J = + 1} ^ {n}はF1 [J] * G [JI] \] 二つの式の右側に同じ形の一部となり、我々は仮定してもよい(F2 [I] = F1 \ [I-N- + 1])\、およそれる\(F1 \)を与えることを反転\(F2 \)を、私たちは私たちの目的を達成することができます:
[Eを\します[I] = \ sum_ {J = 1} ^ {I-1} F1 [J] * G [IJ] - \のsum_ {J = 1} ^ {I-1} F2 [J] * G [IJ] \ ]
多項式の形でコンボリューションと非常に類似して形成観察し、畳み込みは、最初である(I-1 \)は\電源項係数です。したがって、我々は決定されるFFTを使用することができる\(F1 \)\(グラム\)、\ (F2 \)\(グラム\)畳み込み、その後、答えは対応のアイテムの数との差です。

コード

#include <iostream>
#include <cstdio>
#include <cmath>
#define N 400002
using namespace std;
const double PI=acos(-1);
struct Complex{
    double r,i;
}a[N],b[N];
Complex operator + (Complex a,Complex b) {return (Complex){a.r+b.r,a.i+b.i};}
Complex operator - (Complex a,Complex b) {return (Complex){a.r-b.r,a.i-b.i};}
Complex operator * (Complex a,Complex b) {return (Complex){a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r};}
int n=1,m,i,lim=1,r[N];
double f1[N],f2[N],g[N],ansa[N],ansb[N];
void trans()
{
    double tmp[N];
    for(int i=m;i>=1;i--) tmp[m-i+1]=f2[i];
    for(int i=1;i<=m;i++) f2[i]=tmp[i];
}
void FFT(Complex *a,int inv)
{
    for(int i=0;i<n;i++){
        if(i<r[i]) swap(a[i],a[r[i]]);
    }
    for(int l=2;l<=n;l*=2){
        int mid=l/2;
        Complex omg=(Complex){cos(2*PI/l),inv*sin(2*PI/l)};
        for(int i=0;i<n;i+=l){
            Complex w=(Complex){1,0};
            for(int j=0;j<mid;j++,w=w*omg){
                Complex tmp=a[i+j+mid]*w;
                a[i+j+mid]=a[i+j]-tmp;
                a[i+j]=a[i+j]+tmp;
            }
        }
    }
}
void solve(double *f,double *g,double *ans)
{
    for(int i=0;i<n;i++) a[i].r=f[i],a[i].i=0;
    for(int i=0;i<n;i++) b[i].r=g[i],b[i].i=0;
    FFT(a,1);FFT(b,1);
    for(int i=0;i<n;i++) a[i]=a[i]*b[i];
    FFT(a,-1);
    for(int i=1;i<=m;i++) ans[i]=a[i].r/n;
}
int main()
{
    cin>>m;
    while(n<2*m) n*=2;
    while((1<<lim)<n) lim++;
    for(i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(lim-1));
    for(i=1;i<=m;i++){
        cin>>f1[i];
        g[i]=1.0/i/i;
        f2[i]=f1[i];
    }
    trans();
    solve(f1,g,ansa);
    solve(f2,g,ansb);
    for(i=1;i<=m;i++) printf("%.3lf\n",ansa[i]-ansb[m-i+1]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/LSlzf/p/11105283.html