对于从点阵到系数阵,即op=-1时(注:我代码中op=1标示系数阵到点阵,op=-1表示点阵到系数阵),原根应改求其倒数(用逆元算),而不是直接乘上 -1
错误示范:
void NNT(long long *f, long long n,long long op){
for(long long i=0;i<n;++i) if(rev[i] < i) swap(f[i], f[rev[i] ]);
for(long long mid = 1;mid < n;mid <<= 1){
long long j = mid << 1;
long long gn = (qpow(3, (mod - 1) / j) * op + mod) % mod;//就这一行错了
for(long long st = 0;st < n; st += j){
long long g = 1;
for(long long i = st;i < st + mid; ++i, g = g * gn % mod){
long long tmp1 = f[i], tmp2 = g * f[i + mid] % mod;
f[i] = (tmp1 + tmp2) % mod;
f[i + mid] = (tmp1 - tmp2 + mod) % mod;
}
}
}
if(op == -1){
long long inv = qpow(n, mod - 2);
for(long long i = 0; i < n; ++i) f[i] = f[i] * inv % mod;
}
}
正确示范:
void NTT(long long *f, long long n, long long op){
for(long long i = 0; i < n; ++i)
if(rev[i] < i) swap(f[i], f[rev[i]]);
for(long long mid = 1; mid < n; mid <<= 1){
long long j = mid << 1;
long long gn = qpow(3, (mod - 1) / j);
if(op == -1) gn = qpow(gn, mod - 2);//应改求其逆元(qpow可以用费马小定理求逆元)
for(long long st = 0; st < n; st += j){
long long g = 1;
for(long long i = st; i < st + mid; ++i, g = g * gn % mod){
long long tmp1 = f[i], tmp2 = g * f[i + mid] % mod;
f[i] = (tmp1 + tmp2) % mod;
f[i + mid] = (tmp1 - tmp2 + mod) % mod;
}
}
}
if(op == -1){
long long inv = qpow(n, mod - 2);
for(long long i = 0; i < n; ++i) f[i] = f[i] * inv % mod;
}
}