題目連結:BZOJ3527
第一次學會如何寫數學公式,雖然隻是簡單的入門,但還是有點激動。。。
首先這個題很明顯是多項式乘法,但是強迫症的我過于糾結下标,以至于困惑了好久,簡直SB。
注:下标均從0開始。
現在進入正題。
Fj=∑i<jqiqj(i−j)2−∑i>jqiqj(i−j)2
現在我們轉化一下:記住下标從0開始
Fj=∑i=0j−1qiqj(i−j)2−∑i=j+1n−1qiqj(i−j)2
Ej=Fjqj=∑i=0j−1qi(i−j)2−∑i=j+1n−1qi(i−j)2
記 f(i)=qi , g(i)=1i2 ,其中 g(0)=0 有
Ej=∑i=0j−1f(i)∗g(j−i)−∑i=j+1n−1f(i)∗g(j−i)
等号右邊第一個式子 ∑j−1i=0f(i)∗g(j−i)=∑ji=0f(i)∗g(j−i) ,就是卷積的形式,直接FFT算即可。
等号右邊第二個式子 ∑n−1i=j+1f(i)∗g(j−i)=∑n−1i=jf(i)∗g(j−i)=∑n−j−1i=0f(i+j)∗g(i)
倒序處理,令 h(n−1−i−j)=f(i+j) ,有 ∑n−j−1i=0f(i+j)∗g(i)=∑n−j−1i=0h(n−1−i−j)∗g(i) ,記為 Xi=∑n−j−1i=0h(n−1−i−j)∗g(i) ,則 Xn−j−1=∑ji=0h(j−i)∗g(i) ,也是卷積的形式,直接FFT即可。
最後 Ej=∑ji=0f(i)∗g(j−i)−Xn−j−1 ,其中 ∑ji=0f(i)∗g(j−i) 與 Xn−j−1 均可由FFT直接算的,題目即可解決。
代碼如下:
/**************************************************************
Problem: 3527
User: sfailsthy
Language: C++
Result: Accepted
Time:3764 ms
Memory:17680 kb
****************************************************************/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn;
const double PI =acos);
struct Complex{
double real,image;
Complex(){
real=image;
}
Complex(double a,double b){
real=a;
image=b;
}
Complex operator + (const Complex &s) const{
return Complex(real+s.real,image+s.image);
}
Complex operator - (const Complex &s) const{
return Complex(real-s.real,image-s.image);
}
Complex operator * (const Complex &s) const{
return Complex(real*s.real-image*s.image,real*s.image+image*s.real);
}
}x1[maxn],x2[maxn],A[maxn];
int n,rev[maxn];
double a[maxn],b[maxn],c[maxn];
void init(int &len,int len1,int len2){
int k,L,r,t;
while(k*len1||k*len2){
k<<;
L++;
}
len=k;
for(int i;i<len;i++){
t=i,r,k=L;
while(k--){
r<<;
r|=t;
t>>;
}
rev[i]=r;
}
}
void FFT(Complex x[],int len,int op){
Complex u,t;
for(int i;i<len;i++){
A[rev[i]]=x[i];
}
for(int i;i<len;i++){
x[i]=A[i];
}
for(int k;k<=len;k<<){
Complex wn(cos*PI/k*op),sin*PI/k*op));
for(int i;i<len;i+=k){
Complex w);
for(int j;j<k;j++){
u=x[i+j];
t=w*x[i+j+k];
x[i+j]=u+t;
x[i+j+k]=u-t;
w=w*wn;
}
}
}
if(op=){
for(int i;i<len;i++){
x[i].real/=len;
}
}
}
int main(){
scanf("%d",&n);
for(int i;i<n;i++){
scanf("%lf",&a[i]);
}
for(int i;i<n;i++){
b[i]/i/i;
}
int len,len1=n,len2=n;
init(len,len1,len2);
for(int i;i<len;i++){
x1[i]=Complex();
x2[i]=Complex();
}
for(int i;i<len;i++){
x1[i]=Complex(a[i]);
x2[i]=Complex(b[i]);
}
FFT(x1,len);
FFT(x2,len);
for(int i;i<len;i++){
x1[i]=x1[i]*x2[i];
}
FFT(x1,len);
for(int i;i<n;i++){
c[i]=x1[i].real;
}
for(int i;i<len;i++){
x1[i]=Complex();
x2[i]=Complex();
}
for(int i;i<n;i++){
x1[i]=Complex(a[n-i]);
if(i) x2[i]=Complex(b[i]);
}
FFT(x1,len);
FFT(x2,len);
for(int i;i<len;i++){
x1[i]=x1[i]*x2[i];
}
FFT(x1,len);
for(int i;i<n;i++){
c[i]-=x1[n-i].real;
}
for(int i;i<n;i++){
printf("%.3lf\n",c[i]);
}
return;
}