P3338 [ZJOI2014]力 —— FFT

题目链接:点我啊╭(╯^╰)╮

题目大意:

    在这里插入图片描述

解题思路:

     E i = F i q i = j = 1 i q j ( i j ) 2 j = i + 1 n q j ( i j ) 2 E_i=\frac{F_i}{q_i} = \sum_{j=1}^{i} \frac{q_j}{(i-j)^2} - \sum_{j=i+1}^{n} \frac{q_j}{(i-j)^2}
    令 f i = q i f_i=q_i g i = 1 i 2 g_i=\frac{1}{i^2} p i = q n i + 1 p_i=q_{n-i+1}

     E i = j = 1 i f j g i j j = i + 1 n p n j g j i E_i = \sum_{j=1}^{i} f_j g_{i-j} - \sum_{j=i+1}^{n} p_{n-j} g_{j-i}

    两边都是卷积的形式,FFT即可

核心:卷积形式的变换

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
const double pi = acos(-1);
int n, len, rev[maxn<<1];
struct cp {
	double x, y;
	cp(double _x=0, double _y=0) {x = _x, y = _y;}
	cp operator + (const cp &A) const {return cp(x+A.x, y+A.y);}
	cp operator - (const cp &A) const {return cp(x-A.x, y-A.y);}
	cp operator * (const cp &A) const {return cp(x*A.x-y*A.y, x*A.y+y*A.x);}
} f[maxn<<1], p[maxn<<1], g[maxn<<1];

void fft(cp *f, int inv) {
	for(int i=0; i<len; i++) if(i<rev[i]) swap(f[i], f[rev[i]]);
	for(int p=2; p<=len; p<<=1) {	//	区间长度
		int Len = p >> 1;	//	待合并长度
		cp wn(cos(2*pi/p), inv*sin(2*pi/p));
		for(int k=0; k<len; k+=p) {	//	起始点
			cp w(1, 0);
			for(int i=k; i<k+Len; i++) {
				cp tmp = w * f[i+Len];
				f[i+Len] = f[i] - tmp;
				f[i] = f[i] + tmp;
				w = w * wn;
			}
		}
	}
}

int main() {
	scanf("%d", &n);
	for(int i=1; i<=n; i++) {
		scanf("%lf", &f[i].x);	
		p[i].x = f[i].x;
		g[i].x = 1.0 / double(i) / double(i);
	}
	reverse(p+1, p+1+n);
	for(len=1; len<=n+n; len<<=1);
	for(int i=0; i<len; i++) rev[i] = (rev[i>>1]>>1) | ((i&1) ? len>>1 : 0);
	
	fft(f, 1), fft(p, 1), fft(g, 1);
	for(int i=0; i<len; i++) f[i] = f[i] * g[i], p[i] = p[i] * g[i];
	fft(f, -1), fft(p, -1);
	
	for(int i=1; i<=n; i++) f[i].x /= len, p[i].x /= len;
	for(int i=1; i<=n; i++) printf("%.3f\n", f[i].x - p[n-i+1].x);
}
发布了221 篇原创文章 · 获赞 220 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Scar_Halo/article/details/102847439