一、fft模板(來自鄺斌模板)
struct complex
complex operator -(const complex &b)const
complex operator +(const complex &b)const
complex operator *(const complex &b)const
};void change(complex y,int len)
if(j < k) j += k;
}}//len必須是2^k
//on==1進行dft;on==-1進行idft
void fft(complex y,int len,int on)}}
if(on == -1)
}complex x[maxn<<2];
int len,len1;
len = 1;
while(len < 2 * len1) len <<= 1;
for(int i = 0; i < len1; i++)
x[i] = a[i];
for(int i = len1; i < len; i++)
x[i] = complex(0,0);
fft(x,len,1);
fft(x,len,-1);
二、fft詳解請看大佬的blogggn_2015
三、個人理解
1、fft(fast fourier transformation)是離散傅氏變換(dft)的快速演算法。
2、傅利葉變換:能將滿足一定條件的某個函式表示成三角函式或他們的積分的線性組合。
3、卷積定理指出:傅利葉變換可以化複雜的卷積運算為簡單的乘積運算,從而提供了計算卷積的一種簡單手段。
4、卷積是兩個變數在某範圍內相乘後求和的結果。如果卷積的變數是序列x(n)和h(n),則卷積的結果
5、可以看出fft可以用於計算f(n)*g(n)的結果。
6、f(n)*g(n)的結果:
設:f(x) = x+2x^3+x^4,g(x) = x+2x^3+x^4,則
h(x) = f(n)*g(n)
= (x+2x^3+x^4)*(x+2x^3+x^4)
=(x*x+x*2x^3+x*x^4)+(2x^3*x+2x^3*2x^3+2x^3*x^4)+(x^4*x+x^4*2x^3+x^4*x^4)
=x^2+(2+2)x^4+(1+1)x^5+4x^6+(2+2)x^7+x^8(請記住這一步,可以看做是不同位置兩兩相加)
= x^2+4x^4+2x^5+4x^6+4x^7+x^8
7、把f(x)換個形式以符合計算機的使用。令x[i]等於冪為i的係數,如f(x) = 0*x^0+1*x^1+0*x^2+2*x^3+1*x^4,則x =
四、例題
1、hdu4609 給出 n 條線段長度,問任取 3 根,組成三角形的概率。(詳細看鄺斌大神)
num表示長度為i的線段有多少根,現在求線段長度兩兩相加後長度為i的組合有多少種。如果暴力求線段相加的長度則複雜度為o(n^2),會超時。這時考慮到卷積可以求不同位置兩兩相加的結果,而且可以用fft以o(n)的複雜度求出卷積的結果。
現在我們構造f(x)和g(x)函式,令k*x^i表示長度為i的線段(組合)有k根(種),f(x) = sum(num[i] * x^i)。因為現在求線段兩兩組合所以g(x) = f(x)。
fft(x,len,1);//dft使f(x)函式轉化為三角函式或他們的積分的線性組合,便於計算
for(int i = 0; i < len; i++) x[i] = x[i] * x[i];//計算f(x)*g(x)的卷積結果,此時還是三角函式或他們的積分的線性組合的形式
fft(x,len,-1);//idft將三角函式或他們的積分的線性組合的形式轉化為離散點的形式,得到結果
後面就是組合數學的內容了,詳細請看鄺斌大神的題解。
2、gym-101667h 求b在a中選乙個起點開始匹配,能匹配到的位置的最大數量。
簡單想到,先將a的字元轉化s->r,r->p,p->s,表示成哪些字元能得分。接下來也是兩兩匹配,所以我們可以對每種字元分別處理。針對字元s,x1[i]表示a位置i的字元為s則為1,否則為0。此時,如果位置i,j的字元相同則卷積位置i+j的結果為1,否則為0。當卷積結果計算完以後,我們只需檢視sum(x[i+j],x[i+j+2],...,x[i+j+2*len2])(0<=i但是這樣複雜度不能滿足。所以,反轉b,則結果為max(x[i+j+len2],x[i+1+j+len2-1],...,x[i+len2+j+len2-len2]),即max(x[i+j+len2])。
#include#define ms(a, b) memset(a, b, sizeof(a));
#define lowbit(x) (x&(-x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pairpii;
const ll linf = 3e12 + 10;
const int inf = 1e9 + 7;
const int maxn = 1e5 + 10;
const int maxm = 2e3 + 10;
const int maxb = 26;
const int sigma_size = 62;
const double eps = 1e-8;
const int mod = 20071027;
const double pi = acos(-1.0);
const int ha = 2333;
struct complex
complex operator -(const complex &b)const
complex operator +(const complex &b)const
complex operator *(const complex &b)const
};void change(complex y,int len)
if(j < k) j += k;
}}void fft(complex y,int len,int on)}}
if(on == -1)
}complex x1[maxn<<2],x2[maxn<<2];
char str1[maxn],str2[maxn];
int sum[maxn<<2];
int len,len1,len2;
void f(char c)
int main()
len = 1;
while(len < 2 * len1 || len < 2 * len2) len <<= 1;
f('r');
f('p');
f('s');
int ans = 0;
for(int i = len2 - 1; i < len; i++)
ans = max(ans,sum[i]);
printf("%d\n",ans);
}return 0;
}
模板 分治FFT
luogu4721一道模板題 前置知識 fft ntt cdq cdqcd q分治 雖然本人覺得和cdq cdqcd q沒啥關係,應該只用了分治思想 用來解決這樣的式子 f i j 1i f i j g j f i sum i f i j times g j f i j 1i f i j g j 可...
FFT 模板 大數相乘
大數乘法 基準時間限制 2 秒 空間限制 131072 kb 分值 80 難度 5級演算法題 給出2個大整數a,b,計算a b的結果。input 第1行 大數a 第2行 大數b a,b的長度 100000,a,b 0 output 輸出a binput示例 123456 234567 output示...
luogu 模板 分治 FFT
題目背景有提示啊。給定乙個陣列f ff,求gi j 1 igi jf jg i sum g f j gi j 1i gi j fj 考慮寫出g gg的生成函式。g x g x f x g 0 g x g x f x 1g x 1 1 f x beging x g x f x g 0 g x g x ...