設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...