2022.5.21 $\text{FFT/NTT(unfinished)}$
听了两节课了,懂了但没完全懂。
不过倒是听了一点复数和原根的知识
暂且放个代码吧......
\(\text{W! S! F! W!}\)
(有一些来不及整理的截图,见文件)
$\text{F F T}$ 模板
#include
#include
#include
#include
#define MAXN 4000010
int n,m;
struct complex{
double real,imag;
complex(){real=imag=0.0;}
complex(double x){real=x,imag=0.0;}
complex(double x,double y){real=x,imag=y;}
complex operator + (const complex &a)const{
return complex(real+a.real,imag+a.imag);
}
complex operator - (const complex &a)const{
return complex(real-a.real,imag-a.imag);
}
complex operator * (const complex &a)const{
return complex(real*a.real-imag*a.imag,imag*a.real+real*a.imag);
}
void operator /= (const double x){
real/=x,imag/=x;
}
}A[MAXN],B[MAXN],u[MAXN];
int lowbit(int x){
return x&-x;
}
int bit_reverse(int x,int size){
int res=0;
for(int i=x;i;i-=lowbit(i)){
res|=size/2/lowbit(i);
}
return res;
}
void fft(complex *A,int size,bool flag){
for(int i=0;i>1,addgap=size/step;
for(int i=0;i'9') w|=(ch=='-'),ch=getchar();
while(ch>='0' && ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return w?-x:x;
}
int main(){
//freopen("input","r",stdin);
std::cin>>n>>m;n++,m++;
int size=1;
while(size
$\text{f f t}$ 函数
#include
#include
typedef std::complex Comp; // STL complex
const Comp I(0, 1); // i
const int MAX_N = 1 << 20;
Comp tmp[MAX_N];
void DFT(Comp *f, int n, int rev) { // rev=1,DFT; rev=-1,IDFT
if (n == 1) return;
for (int i = 0; i < n; ++i) tmp[i] = f[i];
for (int i = 0; i < n; ++i) { // 偶数放左边,奇数放右边
if (i & 1)
f[n / 2 + i / 2] = tmp[i];
else
f[i / 2] = tmp[i];
}
Comp *g = f, *h = f + n / 2;
DFT(g, n / 2, rev), DFT(h, n / 2, rev); // 递归 DFT
Comp cur(1, 0), step(cos(2 * M_PI / n), sin(2 * M_PI * rev / n));
// Comp step=exp(I*(2*M_PI/n*rev)); // 两个 step 定义是等价的
for (int k = 0; k < n / 2; ++k) {
tmp[k] = g[k] + cur * h[k];
tmp[k + n / 2] = g[k] - cur * h[k];
cur *= step;
}
for (int i = 0; i < n; ++i) f[i] = tmp[i];
}
$\text{N T T}$
#include
#include
using namespace std;
typedef long long ll;
const int N=1e7+5,P=998244353,P1=3,P2=332748118; // P2是P1的逆元
int lena,lenb,n=1,lim,r[N];
ll a[N],b[N];
ll rpow(ll x,ll y){//要手打
ll res=1;
while(y){
if(y&1)res=(res*x)%P;
x=(x*x)%P;
y>>=1;
}
return res%P;
}
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void NTT(ll *A,int tp){
for(int i=0;i>1]>>1)|((i&1)<<(lim-1));
NTT(a,1);
NTT(b,1);
for(int i=0;i<=n;i++)a[i]=(a[i]*b[i])%P;
NTT(a,0);
ll inv=rpow(n,P-2);
for(int i=0;i<=lena+lenb;i++)printf("%d ",(a[i]*inv)%P);
}