这题…我可能是唯一一个用三种语言各写一遍的人
然而Pascal卡不过去
并且我应该是第一个用C写FFT通过的(
所以这篇题解的重点不在数学,而在如何用C愉快地食用FFT(
既然前面有P党卡过去发题解那这个应该也行吧
先重复一下做法:把两个多项式变换成点值表示,直接 O ( n ) O(n) O(n)乘起来,然后变回系数表示就是了。。。
然后进正题
由于C++有面向对象、函数重载等一系列特性,复数运算很容易以优美的方式呈现
然而C既不能重载函数,也难以面向对象…
然而在研究std::complex
的时候,我们发现它的头文件include
了一个complex.h
库…
于是上网学习,发现C也有复数库(其实甚至不需要库,在C99中复数已经是内建类型了)
于是就极度舒适(
FFT需要的基本用法:
#include<complex.h>//为了方便而包含,实际可以省略,但声明变量需将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<stdio.h>
#include<ctype.h>
#include<math.h>
#include<complex.h>
char gc(void)
{
static char buf[1<<16],*p1=buf,*p2=buf;
if(p1==p2)
{
p2=(p1=buf)+fread(buf,1,1<<16,stdin);
if