给2个大小为n的数组,求卷积的最大值
fft
sum1是x(n+1)的系数sum2是x(n+2)的系数和x2的系数和,类推,fft跑一遍复杂度nlogn
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rt register int
#define ll long long
#define r read()
using namespace std;
ll read()
{
ll x = 0; int zf = 1; char ch;
while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
if (ch == '-') zf = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}
void write(ll y)
{
if (y < 0) putchar('-'), y = -y;
if (y > 9) write(y / 10);
putchar(y % 10 + '0');
}
inline void writeln(ll x)
{
write(x);putchar('\n');
}
int i,j,k,m,n,x,y,z,cnt,all,num,li,lim;
int low[2200010];//low数组就是底层的reverse序列
struct cp{
double x,y;
}a[2200010],b[2200010];
inline cp operator + (const cp x,const cp y){return {x.x+y.x, x.y+y.y};}
inline cp operator - (const cp x,const cp y){return {x.x-y.x, x.y-y.y};}
inline cp operator * (const cp x,const cp y){return {x.x*y.x-x.y*y.y, x.x*y.y+x.y*y.x};}
double PI=acos(-1.0);
void FFT(cp *A,const int fla)
{
for(rt i=0;i<lim;i++) if(i<low[i])swap(A[i],A[low[i]]);//得到底层数列
for(rt i=1;i<lim;i<<=1)//i表示当前层的下面每个区间大小为i
{
cp w={cos(PI/i),fla*sin(PI/i)};//本应为2PI/2i
for(rt j=0;j<lim;j+=(i<<1))//j为当前层的每个起始端点
{
cp K={1,0};
for(rt k=0;k<i;k++,K=K*w)//k枚举当前层的j所在区间的元素
{
const cp x=A[j+k],y=K*A[j+k+i];//求解,如果对递归理解深刻应该能理解这段
A[j+k]=x+y;
A[j+k+i]=x-y;
}
}
}
}
int main()
{
n=r, n-=1, m=n;
for(rt i=0;i<=m;i++)a[i].x=r, b[n-i].x=r;
lim=1;while(lim<=n+m)lim*=2,li++;
for(rt i=0;i<lim;i++)
low[i]=(low[i>>1]>>1)+((i&1)<<(li-1));
FFT(a,1);FFT(b,1);
for(rt i=0;i<lim;i++)a[i]=a[i]*b[i];
FFT(a,-1);
// for(rt i=0;i<=(n+m);i++)printf("%d ",(int)(a[i].x/lim+0.5));
ll ans=(ll)(a[n].x/lim+0.5);
for(int i=0; i<=n-1; i++)
{
ans=max(ans,(ll)(a[i].x/lim+0.5)+(ll)(a[i+n+1].x/lim+0.5));
}
printf("%lld", ans);
return 0;
}