前言
以前一直知道FFT的这个思想,一直没有实现。
本想着转C语言抛弃P语言后就码一码。
但最近遇到了奇怪的题目,要用到NTT。
于是就学了一发,借着各种板子好歹是学会了。
简介
NTT是什么?
其实就是FFT,一样是求多项式卷积之类的东东。只不过没有利用到复数里面单位根的性质。
有什么用?
可以实现取模操作!
具体操作
原根:
百度百科的欧拉函数比较费解。
其实解释起来就是对于一个数P
g是它的原根当且仅当g满足:
对
于
任
意
的
x
(
0
<
=
x
<
P
−
1
)
g
x
m
o
d
P
互
不
相
同
对于任意的x(0<=x<P-1)g^xmod\ P互不相同
对于任意的x(0<=x<P−1)gxmod P互不相同
根据这个玩意儿,很容易判断出一个数g是不是P的原根。
显然:当P是一个质数时,一定有原根。
对于原根,都比较难找(只能暴力),但对于一个质数的原根,都很小。
比如998244353,1004535809,469762049这三个数的原根为3.
原根的用处:
我们看到之前FFT里面的单位根:
ω
n
i
\omega_n^i
ωni
我们直接把上面这个单位根替换成原根即可。
怎么替换?
ω
n
i
=
g
i
∗
⌊
(
m
o
−
1
)
n
⌋
(
m
o
是
模
数
)
\omega_n^i=g^{i*\lfloor\frac{(mo-1)}n\rfloor}(mo是模数)
ωni=gi∗⌊n(mo−1)⌋(mo是模数)
直接套上FFT板子即可。
为什么:
我们知道,FFT是利用单位根的几个重要性质来加速的。
那么换成原根之后,只需要满足单位根那几个性质就可以了。
怎么满足呢?
我们知道,单位根满足:
1、全部都不相同
2、
ω
n
x
ω
n
y
=
ω
n
x
+
y
=
ω
n
(
x
+
y
)
m
o
d
n
\omega_n^x\omega_n^y=\omega_n^{x+y}=\omega_n^{(x+y)mod n}
ωnxωny=ωnx+y=ωn(x+y)modn
然后利用这两个性质推出其他性质。
那么原根是否也可以呢?
1、
g
i
∗
⌊
(
m
o
−
1
)
n
⌋
g^{i*\lfloor\frac{(mo-1)}n\rfloor}
gi∗⌊n(mo−1)⌋这个玩意儿右边是一样的,左边的i是不定的。
而且这个g由于是原根,模mo的意义下是都不同的。
得证
2、这个性质其实对模数要求很高。
比如这个模数:1004535809(479 * 2 ^21 + 1)
我们发现,这个模数就很棒,对于一个比较大的n(2的某次方)可以整除。
那么可以容易消去下取整。
接下来就好搞了:
g
x
∗
(
m
o
−
1
)
n
∗
g
y
∗
(
m
o
−
1
)
n
g^{x*\frac{(mo-1)}n}*g^{y*\frac{(mo-1)}n}
gx∗n(mo−1)∗gy∗n(mo−1)
容易变成:
(
g
x
)
(
m
o
−
1
)
n
∗
(
g
y
)
(
m
o
−
1
)
n
(g^x)^{\frac{(mo-1)}n}*(g^y)^{\frac{(mo-1)}n}
(gx)n(mo−1)∗(gy)n(mo−1)
(
g
(
x
+
y
)
)
(
m
o
−
1
)
n
{(g^{(x+y)})}^\frac{(mo-1)}n
(g(x+y))n(mo−1)
已知:
(
g
n
)
(
m
o
−
1
)
n
=
g
m
o
−
1
{(g^{n})}^\frac{(mo-1)}n=g^{mo-1}
(gn)n(mo−1)=gmo−1
根据费马小定理:
g
m
o
−
1
=
1
g^{mo-1}=1
gmo−1=1
所以说:
(
g
(
x
+
y
)
)
(
m
o
−
1
)
n
=
(
g
(
x
+
y
)
m
o
d
n
)
(
m
o
−
1
)
n
{(g^{(x+y)})}^\frac{(mo-1)}n={(g^{(x+y)mod\ n})}^\frac{(mo-1)}n
(g(x+y))n(mo−1)=(g(x+y)mod n)n(mo−1)
那么就意味着可以利用原根来代替单位根搞了。
其他什么性质就不推了。
应用(板子)
我们发现,NTT与FFT的流程、时间都是一样的。
这玩意似乎很棒,比起FFT有以下优点:
1、可以取模
2、避免FFT的精度问题
但是,有优点也有缺点:
1、模数通常很头疼(为什么可以往下翻)
2、常数大(可能是我不会卡常)
一个套路——通常看到一个卷积的形式并且模数为:998244353,1004535809,469762049时,可以考虑NTT了。
板子放在例题里了,自己去看
洛谷P3803 【模板】多项式乘法(FFT)(话说这题我NTT还TLE了)
JZOJ3303. 【集训队互测2013】城市规划(时限良心)
拓展
有时候NTT模数不得,怎么办?
据说可以利用上面的三个模数搞,搞完后用中国剩余定理。
(据说还有很恶心的题,然鹅我没有做多少)