BZOJ4836 二元運算(分治FFT)

2022-05-22 00:00:12 字數 1680 閱讀 2943

設a(n)為a中n的個數,b(n)為b中n的個數。如果只考慮加法顯然是乙個卷積,減法翻轉一下也顯然是乙個卷積。

問題在於兩者都有。容易想到分開處理。那麼可以考慮分治。即對於值域區間[l,r],分別計算a[l,mid]和b[mid+1,r]的貢獻及a[mid+1,r]和b[l,mid]的貢獻,然後再遞迴處理[l,mid]和[mid+1,r]。一定程度上類似於cdq分治。

注意結果可能爆int,用ntt的話不太方便。

#include#include

#include

#include

#include

#include

using

namespace

std;

intread()

while (c>='

0'&&c<='

9') x=(x<<1)+(x<<3)+(c^48),c=getchar();

return x*f;

}#define n 270000

const

double pi=3.14159265358979324

;struct

complex

; }

complex

operator -(const complex&a) const

; }

complex

operator *(const complex&a) const

; }

}c[n],d[n];

intt,n,m,q,a[n],b[n],r[n];

long

long

f[n];

void dft(int n,complex *a,intp);

for (int j=0;ji)

;for (int k=j;k>1);k++,w=w*wn)}}

}void mul(int n,complex *a,complex *b)

void solve(int l,int

r)

int mid=l+r>>1

; solve(l,mid);

solve(mid+1

,r);

int t=1;while (t1) t<<=1

;

for (int i=0;i0

;

for (int i=l;i<=mid;i++) c[i-l].x=a[i];

for (int i=mid+1;i<=r;i++) d[i-mid-1].x=b[i];

mul(t,c,d);

for (int i=l+mid+1;i<=mid+r;i++) f[i]+=(long

long)(c[i-l-mid-1].x+0.5

);

for (int i=0;i0

;

for (int i=mid+1;i<=r;i++) c[i-mid-1].x=a[i];

for (int i=l;i<=mid;i++) d[mid-i].x=b[i];

mul(t,c,d);

for (int i=1;i<=r-l;i++) f[i]+=(long

long)(c[i-1].x+0.5);}

intmain()

return0;

}

BZOJ4836 二元運算 分治FFT

time limit 8 sec memory limit 128 mb submit 578 solved 202 submit status discuss 定義二元運算 opt 滿足 現在給定乙個長為 n 的數列 a 和乙個長為 m 的數列 b 接下來有 q 次詢問。每次詢問給定乙個數字 c ...

bzoj 4836 二元運算

死活tle.求助 update 4.3 23 08 求助了tls之後終於過了.分治裡次數界寫崩了.r l 1就行.分治的做法很神奇!本題的限制在於操作型別與權值相對大小有關,而用 l,mid 更新 mid 1,r 正好適應了本題的要求 include include include include ...

二元運算子過載

siwuxie095 二元運算子過載 所謂 二元運算子,即 這個符號與兩個運算元進行運算 1 加號 的過載 加號 的過載方式有兩種 一種是友元函式過載,一種是成員函式過載 1 先來看成員函式過載,如下 定義乙個座標類 coordinate 在類中宣告成員函式 operator 它的引數是 const...