這題…我可能是唯一乙個用三種語言各寫一遍的人
然而pascal卡不過去
並且我應該是第乙個用c寫fft通過的(
所以這篇題解的重點不在數學,而在如何用c愉快地食用fft(
既然前面有p黨卡過去發題解那這個應該也行吧
先重複一下做法:把兩個多項式變換成點值表示,直接o(n
)o(n)
o(n)
乘起來,然後變回係數表示就是了。。。
然後進正題
由於c++有物件導向、函式過載等一系列特性,複數運算很容易以優美的方式呈現
然而c既不能過載函式,也難以物件導向…
然而在研究std::complex
的時候,我們發現它的標頭檔案include
了乙個complex.h
庫…
於是上網學習,發現c也有複數庫(其實甚至不需要庫,在c99中複數已經是內建型別了)
於是就極度舒適(
fft需要的基本用法:
#include
//為了方便而包含,實際可以省略,但宣告變數需將complex改為_complex
double complex a;
//宣告基於double的複數變數
creal
(a)//取a的實部
cimag
(a)//取a的虛部a=1
+2*_complex_i//_complex_i即是單位虛數i
//另外不擔心重名可以用i代替_complex_i
//然後不考慮可移植性的話,在gcc下提供1.0fi,1.0i,1.0li等寫法
//同時從c++14開始,類似的1.0if,1.0i,1.0il是標準的虛數字面量
然後大量的c數學函式均有針對複數特化的泛型函式,在名字前寫字首c
就是了
於是有了神奇的複數,我們就可以愉快地搞fft了(
然後是不開io優化卡不過去的**
#include
#include
#include
#include
chargc(
void
)return
*p1++;}
// #define gc getchar
void
read
(int
*x)}
void
write
(int x)
#define n (1<<21)
#define pi 3.141592653589793238462643383
int n,m;
double complex a[n]
,b[n]
;int rev[n]
;void
getrev
(int n)
}void
fft(
double complex *a,
int n,
int dft)
}for
(int step=
1;step}}
if(dft==-1
)}intmain
(void
)for
(int i=
0;i<=m;
++i)
int len=1;
while
(len<=n+m+
1)len<<=1;
getrev
(len)
;fft
(a,len,1)
;fft
(b,len,1)
;for
(int i=
0;i++i)a[i]
*=b[i]
;fft
(a,len,-1
);for(
int i=
0;i++i)
}
awsl為什麼這題突然減小時限卡常數啊
警告,若編譯器有__stdc_no_complex__
巨集,則不支援複數(gcc可以放心
最後,雖然我是個c++&物件導向的死忠粉,但還是要說一句:
P3803 模板 多項式乘法(FFT)
p3803 模板 多項式乘法 fft 給定乙個 n 次多項式 f x 和乙個 m 次多項式 g x 請求出 f x 和 g x 的卷積。從低到高輸出f x g x 的係數 另一種問法 如果有兩個無限序列a和b,那麼它們卷積的結果是 求出yn值 模板題建議背過模板 講的非常不錯的部落格 include...
洛谷 P3803 模板 多項式乘法(FFT)
fft模板題 單向膜拜 從多項式乘法到快速傅利葉變換 fft 學習筆記 大致理解為將多項式從係數表示法轉化為點值表示法然後再變回係數表示法 include include include define n 2621450 define pi acos 1.0 using namespace std ...
洛谷P3803 模板 多項式乘法 NTT
題目傳送門 給定乙個n次多項式f x 和乙個m次多項式g x 請求出f x 和g x 的卷積。輸入格式 第一行2個正整數n,m。接下來一行n 1個數字,從低到高表示f x 的係數。接下來一行m 1個數字,從低到高表示g x 的係數。輸出格式 一行n m 1個數字,從低到高表示f x g x 的係數。...