2个循环数组求卷积的最大值

给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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值