ZJOI2014 力
阿新 • • 發佈:2018-12-12
一道FFT的標準練習題。
把\(q_i\)除進去,就可以得到\(E(j) = \sum_{i<j}\frac{q_j}{(i-j)^2} - \sum_{i > j}\frac{q_j}{(i-j)^2}\).
把這個式子前後兩部分分別拆開,設\(f(i) = q_i\),\(g(i) = \frac{1}{i^2}\),那麼前一部分就是\(\sum_{i=0}^j f(j) * g(i-j)\),而後一部分就是\(\sum_{i = 0}^{n - j - 1}f(i+j) * g(j)\)
後半部分好像不大好維護……我們把整個序列調過來,用\(f1\)表示\(f\)
那麼前後兩個式子都符合了卷積的形式,可以使用FFT求解。然後它問的每一個\(E_i\)相對應地就是每一個係數。
看一下程式碼。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<set> #include<vector> #include<map> #include<queue> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') #define fr friend inline #define y1 poj #define mp make_pair #define pr pair<int,int> #define fi first #define sc second #define pb push_back using namespace std; typedef long long ll; const int M = 200005; const int INF = 1000000009; const double eps = 1e-7; const double pi = acos(-1); const ll mod = 998244353; ll read() { ll ans = 0,op = 1;char ch = getchar(); while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();} while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar(); return ans * op; } struct Comp { double x,y; Comp(){} Comp(double px,double py){x = px,y = py;} fr Comp operator + (const Comp &a,const Comp &b) {return (Comp){a.x + b.x,a.y + b.y};} fr Comp operator - (const Comp &a,const Comp &b) {return (Comp){a.x - b.x,a.y - b.y};} fr Comp operator * (const Comp &a,const Comp &b) {return (Comp){a.x * b.x - a.y * b.y,a.y * b.x + a.x * b.y};} }f[M<<1],g[M<<1],f1[M<<1],kx,ky; int n,rev[M<<1],len = 1,L; double c[M<<1]; void fft(Comp *a,int f) { rep(i,0,len-1) if(i < rev[i]) swap(a[i],a[rev[i]]); for(int i = 1;i < len;i <<= 1) { Comp omg1(cos(pi / i),f * sin(pi / i)); for(int j = 0;j < len;j += (i << 1)) { Comp omg(1,0); rep(k,0,i-1) { kx = a[j+k],ky = omg * a[j+k+i]; a[j+k] = kx + ky,a[j+k+i] = kx - ky,omg = omg * omg1; } } } } int main() { n = read() - 1; rep(i,0,n) { scanf("%lf",&f[i].x),f1[n-i].x = f[i].x; if(i) g[i].x = 1.0 / double(i) / double(i); } while(len <= n << 1) len <<= 1,L++; rep(i,0,len-1) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (L-1)); fft(f,1),fft(f1,1),fft(g,1); rep(i,0,len-1) f[i] = f[i] * g[i],f1[i] = f1[i] * g[i]; fft(f,-1),fft(f1,-1); rep(i,0,n) c[i] = (f[i].x - f1[n - i].x) / len; rep(i,0,n) printf("%.3lf\n",c[i]); return 0; }