[Zjoi2014]力
题面
给出n个数qi,给出Fj的定义如下:
令Ei=Fi/qi,求Ei.
Input
第一行一个整数n。
接下来n行每行输入一个数,第i行表示qi。
n≤100000,0<qi<1000000000
Output
n行,第i行输出Ei。与标准答案误差不超过1e-2即可。
题解
有人说,这是一道快速傅里叶变换(FFT)板子题。
看到这个式子,感觉有点难,但是我们把Ei表示出来
把E拆开,
把右半边求出来,设,那么
,我们发现,A已经是卷积的形式了,可以用FFT做,
把B转换一下,设B翻转过来的数组为B',q翻转过来的数组为q',那么,就可以用FFT求B了。
CODE
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<algorithm>
#define LL long long
#define MAXN 200005
#pragma GCC optimize(2)
#pragma G++ optimize(3)
#define rg register
#define DB double
using namespace std;
inline int read() {
	int f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();}
	while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();}
	return x * f;
}
struct Omiga{
	DB a,b;
	inline Omiga(){a = b = 0.0;}
	inline Omiga(DB A,DB B){a = A,b = B;}
}w;
inline Omiga operator + (Omiga x,Omiga y) {
	return Omiga(x.a + y.a,x.b + y.b);
}
inline Omiga operator - (Omiga x,Omiga y) {
	return Omiga(x.a - y.a,x.b - y.b);
}
inline Omiga operator * (Omiga x,Omiga y) {
	return Omiga(x.a*y.a - x.b*y.b,x.a*y.b + x.b*y.a);
}
inline Omiga operator / (Omiga x,DB y) {
	return Omiga(x.a / y,x.b / y);
}
const DB PI = acos(-1);
int fan[MAXN*3];
inline void FFT(int len,Omiga *a,int temp) {
	int ugly = log2(len);
	fan[0] = 0;
	for(rg int i = 1;i < len;i ++) {
		fan[i] = (((fan[i>>1]>>1))|((i&1)<<(ugly-1)));
		if(fan[i] < i) swap(a[fan[i]],a[i]);
	}
	for(rg int k = 2;k <= len;k <<= 1) {
		int t = k / 2;
		Omiga vw(cos(temp*PI/t)*1.0,sin(temp*PI/t)*1.0);
		for(rg int i = 0;i < len;i += k) {
			Omiga w2(1.0,0.0);
			for(rg int j = 0;j < t;j ++,w2 = w2*vw) {
				Omiga w3 = a[i + j],w4 = a[i + j + t];
				a[i + j] = w3 + w4*w2;
				a[i + j + t] = w3 - w4*w2;
			}
		}
	}
	if(temp == -1) for(rg int i = 0;i <= len;i ++) {
		a[i] = a[i] / (DB)len;
	}
	return ;
}
int n,m,q,i,j,s,o,k,t;
Omiga F[MAXN*3],G[MAXN*3],AS[MAXN*3];
void juanji(Omiga *A,Omiga *B,Omiga *C,int lena,int lenb,int &lenc) {
	int nm = lena + lenb;
	int len = 1;
	len = 1<<(int)ceil(log2(nm));
	if(len==nm) len<<=1;
	FFT(len,A,1);FFT(len,B,1);
	for(rg int i = 0;i <= len;i ++) C[i] = A[i]*B[i];
	FFT(len,C,-1);
	lenc = len;
}
DB qi[MAXN];
DB ans[MAXN];
int main() {
	n = read();
	for(rg int i = 1;i <= n;i ++) {
		scanf("%lf",&qi[i]);
	}
	for(rg int i = 0;i < n;i ++) F[i].a = qi[i+1],F[i].b = 0.0;
	G[0].a = 0.0;G[0].b = 0.0;
	for(rg int i = 1;i < n;i ++) G[i].a = 1.0 / ((DB)i*i),G[i].b = 0.0;
	juanji(F,G,AS,n - 1,n - 1,m);
	for(rg int i = 0;i < n;i ++) {
		ans[i+1] += AS[i].a;
	}
	for(rg int i = 0;i <= m;i ++) F[i] = G[i] = AS[i] = w;
	for(rg int i = 0;i < n;i ++) F[i].a = qi[n - i],F[i].b = 0.0;
	G[0].a = 0.0;G[0].b = 0.0;
	for(rg int i = 1;i < n;i ++) G[i].a = 1.0 / ((DB)i*1.0*i),G[i].b = 0.0;
	juanji(F,G,AS,n - 1,n - 1,m);
	for(rg int i = 1;i <= n;i ++) {
		ans[i] -= AS[n - i].a;
	}
	for(rg int i = 1;i <= n;i ++) {
		printf("%.3lf\n",ans[i]);
	}
	return 0;
}
                    
                
                
            
        
浙公网安备 33010602011771号