[Note] CRT&ExCRT&任意模数NTT&MTT&分治FFT

参考 jklover 的笔记
参考 rvalue 的笔记
参考 yx 的笔记
参考 Great_Influence 的笔记
参考 zerol 的笔记


CRT

解模数互质的线性同余方程组 { x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) x ≡ a 3 ( m o d m 3 ) ⋮ x ≡ a n ( m o d m n ) \begin{cases} \begin{array}{rcl} x&\equiv& a_1\pmod{m_1}\\ x&\equiv& a_2\pmod{m_2}\\ x&\equiv& a_3\pmod{m_3}\\ &\vdots&\\ x&\equiv& a_n\pmod{m_n}\\ \end{array} \end{cases} xxxxa1(modm1)a2(modm2)a3(modm3)an(modmn)

其中,模数 m 1 ⋯ m n m_1\cdots m_n m1mn 两两互质(并不要求全部都是素数)。


怎么解呢……我先不讲思路,你对着下面的过程康一遍?

N = ∏ i = 1 n m i N=\prod\limits_{i=1}^nm_i N=i=1nmi

  • 考虑到 m i m_i mi N m i \frac{N}{m_i} miN 互质,
    对每个 i i i 用寻找 y i y_i yi 满足 N m i ⋅ y i ≡ 1 ( m o d m i ) \frac{N}{m_i}\cdot y_i\equiv1\pmod{m_i} miNyi1(modmi)

  • 为了方便记 x i = N m i ⋅ y i x_i=\frac{N}{m_i}\cdot y_i xi=miNyi
    那么有:

x i a i ≡ a i ( m o d m i ) x_ia_i\equiv a_i\pmod{m_i} xiaiai(modmi)

  • 并且 x i a i = N y i a i m i x_ia_i=\frac{Ny_ia_i}{m_i} xiai=miNyiai
    显然 ∀ j ≠ i \forall j\ne i j̸=i m j ∣ N m i m_j|\frac{N}{m_i} mjmiN
    那么有:

x i a i ≡ 0 ( m o d m j ) x_ia_i\equiv0\pmod{m_j} xiai0(modmj)

上面的东西简单讲就是 x i ≡ N m i ⋅ [ ( N m i ) − 1 m o d    m i ] ( m o d N ) x_i\equiv\frac{N}{m_i}\cdot\left[(\frac{N}{m_i})^{\bm-1}\mod{m_i}\right]\pmod{N} ximiN[(miN)1modmi](modN)
不难发现这个东西的大体思路跟拉格朗日插值是很像的
显而易见地: x ≡ ∑ i = 1 n x i a i ( m o d N ) x\equiv\sum\limits_{i=1}^nx_ia_i\pmod{N} xi=1nxiai(modN) 总复杂度 O ( n log ⁡ N ) O(n\log N) O(nlogN)


ExCRT

解任意模数的线性同余方程组 { x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) x ≡ a 3 ( m o d m 3 ) ⋮ x ≡ a n ( m o d m n ) \begin{cases} \begin{array}{rcl} x&\equiv& a_1\pmod{m_1}\\ x&\equiv& a_2\pmod{m_2}\\ x&\equiv& a_3\pmod{m_3}\\ &\vdots&\\ x&\equiv& a_n\pmod{m_n}\\ \end{array} \end{cases} xxxxa1(modm1)a2(modm2)a3(modm3)an(modmn)

复杂度跟 CRT 一毛一样。
它的想法很简单暴力,就是把方程两两逐个合并

考虑 { x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) \begin{cases}\begin{array}{rcl} x&\equiv& a_1\pmod{m_1}\\ x&\equiv& a_2\pmod{m_2}\\ \end{array}\end{cases} {xxa1(modm1)a2(modm2)

x 0 = k 1 m 1 + a 1 = k 2 m 2 + a 2 x_0=k_1m_1+a_1=k_2m_2+a_2 x0=k1m1+a1=k2m2+a2
k 1 m 1 − k 2 m 2 = ( a 2 − a 1 ) k_1m_1-k_2m_2=(a_2-a_1) k1m1k2m2=(a2a1) 直接裸上 ExGCD
k 1 k_1 k1 或者 k 2 k_2 k2 m 2 m_2 m2 或者 m 1 m_1 m1 取模(避免过大)然后代回自家式子

为什么交叉取模?你可以考虑挪一下就变成两条式子:

{ k 1 m 1 ≡ a 2 − a 1 ( m o d m 2 ) k 2 m 2 ≡ a 1 − a 2 ( m o d m 1 ) \begin{cases}\begin{array}{rcl} k_1m_1&\equiv& a_2-a_1\pmod{m_2}\\ k_2m_2&\equiv& a_1-a_2\pmod{m_1}\\ \end{array}\end{cases} {k1m1k2m2a2a1(modm2)a1a2(modm1)

解出 x 0 x_0 x0 得到合并后的方程 x ≡ x 0 ( m o d [ m 1 , m 2 ] ) x\equiv x_0\pmod{[m_1,m_2]} xx0(mod[m1,m2]) [ m 1 , m 2 ] [m_1,m_2] [m1,m2] l c m ( m 1 , m 2 ) lcm(m_1,m_2) lcm(m1,m2)
一路合并最后得到一个方程,方程右边就是解。


NTT模数

常用的几个模数(最小正原根皆为 3 )
- 469762049
- 998244353
- 1004535809
- 1997585853 \small{\colorbox{#000000}{\color{black}1997585853}} 1997585853划掉以防我记混,实际上一般记住三个就够了
如果现场忘了(也许)也可以打表,枚举 k k k p = r 2 k + 1 p=r2^k+1 p=r2k+1


任意模数NTT

有时候遇到 NTT 题却不给常规的 NTT 模数
比如猫猫可能会给你一个 998244853
长度为 n n n 的卷积模数为 m m m 那么最后得到的不取模的答案显然不超过 n m 2 nm^2 nm2
就可以拆开
{ x ≡ a 1 ( m o d p 1 ) x ≡ a 2 ( m o d p 2 ) x ≡ a 3 ( m o d p 3 ) \begin{cases} x\equiv a_1\pmod{p_1}\\ x\equiv a_2\pmod{p_2}\\ x\equiv a_3\pmod{p_3} \end{cases} xa1(modp1)xa2(modp2)xa3(modp3)
但是直接搞的话模数会爆炸

一个方法是先合并前两个得到 x ≡ A ( m o d M ) x\equiv A\pmod{M} xA(modM)
x ≡ k M + A ( m o d m ) x\equiv kM+A\pmod{m} xkM+A(modm)
k M + A ≡ a 3 ( m o d p 3 ) kM+A\equiv a_3\pmod{p_3} kM+Aa3(modp3) 那么 k ≡ ( a 3 − A ) M − 1 ( m o d p 3 ) k\equiv(a_3-A)M^{-1}\pmod{p_3} k(a3A)M1(modp3) 代入上去
解得。

注意在这个过程中(合并前两个同余方程以后),乘法要全程用龟速乘法取模
以免爆 __int64

不过它跑得巨慢


MTT

double 的精度可以稳定承受 1 0 14 10^{14} 1014
所以把系数都拆成 2 15 a + b 2^{15}a+b 215a+b
( 2 15 A + B ) ( 2 15 C + D ) = 2 30 A C + 2 15 ( A D + B C ) + B D (2^{15}A+B)(2^{15}C+D)=2^{30}AC+2^{15}(AD+BC)+BD (215A+B)(215C+D)=230AC+215(AD+BC)+BD
这样的话最多大约是 2 30 × 1 0 5 2^{30}\times 10^5 230×105 ,一般会用到 MTT 的题最多也就是这样。
然后带上共轭优化可以优化常数 八次FFT降到四次
还可以降到3.5次(没必要


分治FFT(不取模)

f ( n ) = ∑ i = 1 n f ( n − i ) g ( i ) f(n)=\sum\limits_{i=1}^nf(n-i)g(i) f(n)=i=1nf(ni)g(i)
换句话说也就是由 ∑ i = 0 n f ( i ) g ( n − i ) = 0 \sum\limits_{i=0}^nf(i)g(n-i)=0 i=0nf(i)g(ni)=0 推来的。
实际上可以解决 f ( n ) = a f ( n − b ) + c + ∑ i = 1 n d f ( n − i ) g ( i ) f(n)=af(n-b)+c+\sum\limits_{i=1}^ndf(n-i)g(i) f(n)=af(nb)+c+i=1ndf(ni)g(i)

怎么做?
如果对每个 f ( n ) f(n) f(n) 都 FFT 的话不如直接暴力乘法

分治,每一层对右边的点 x ∈ ( M i d , R ] x\in(Mid,R] x(Mid,R] 只考虑左边的贡献 ω x = ∑ i = L M i d f ( i ) g ( x − i ) \omega_x=\sum\limits_{i=L}^{Mid}f(i)g(x-i) ωx=i=LMidf(i)g(xi)

注意分治的时候要按照

递归左子区间 → 当前(算好左边对右边的贡献) → 递归右子区间

的顺序来进行。


分治FFT(取模)

f ( n ) ≡ ∑ i = 1 n f ( n − i ) g ( i ) ( m o d p ) f(n)\equiv\sum\limits_{i=1}^nf(n-i)g(i)\pmod{p} f(n)i=1nf(ni)g(i)(modp)
生成函数。 F = F ⊗ G − f ( 0 ) g ( n ) F=F\otimes G-f(0)g(n) F=FGf(0)g(n)
F ⊗ ( 1 − G ) ≡ f ( 0 ) g ( n ) ( m o d p ) F\otimes (1-G)\equiv f(0)g(n)\pmod{p} F(1G)f(0)g(n)(modp)
F ≡ ( 1 − G ) − 1 f ( 0 ) g ( n ) ( m o d p ) F\equiv (1-G)^{-1}f(0)g(n)\pmod{p} F(1G)1f(0)g(n)(modp)
多项式求逆。


FWT

离散卷积:
c k = ∑ i ∘ j = k a i b j c_k=\sum\limits_{i\circ j=k}a_ib_j ck=ij=kaibj

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值