概述
文章目录
- 多项式乘法的一些小Trick
- 关于差的“卷积”
- 关于min/max的卷积
- 例题
- T1(Luogu P6300)
- Description
- Solution
- T2(Luogu P3338)
- Description
- Solution
- T3(Luogu P3321)
- Description
- Solution
多项式乘法的一些小Trick
关于差的“卷积”
众所周知,FFT/NTT 能够快速求出下面的数组 c c c
c i = ∑ j = 0 i a j b i − j c_i=sum_{j=0}^i a_j b_{i-j} ci=j=0∑iajbi−j
但是,有的时候,我们要求的却是
c i = ∑ j = 0 n − i a j b i + j c_i=sum_{j=0}^{n-i} a_j b_{i+j} ci=j=0∑n−iajbi+j
这显然不是卷积形式了。不慌,我们考虑将 a a a给翻转一下,即
c i = ∑ j = 0 n − i a n + 1 − j b i + j c_i=sum_{j=0}^{n-i} a_{n+1-j} b_{i+j} ci=j=0∑n−ian+1−jbi+j
由于 ( n + 1 ) − j + ( i + j ) = n + i + 1 (n+1)-j+(i+j)=n+i+1 (n+1)−j+(i+j)=n+i+1与 j j j无关,所以我们只需要将翻转后的 a a a与 b b b求一遍卷积得到 d d d,那么 c i = d n + 1 + i c_i=d_{n+1+i} ci=dn+1+i。
关于min/max的卷积
此时我们要求的是 ∑ i = 0 n m i n ( a i , b n − i ) sum_{i=0}^n min(a_i,b_{n-i}) ∑i=0nmin(ai,bn−i)(以 m i n min min为例)。
这个式子不能直接用FFT/NTT去求。由于自然数 p p p满足 p = ∑ i = 1 ∞ [ i ≤ p ] p=sum_{i=1}^{∞} [i le p] p=∑i=1∞[i≤p],从而原式可以化为
∑ j = 1 ∞ ∑ i = 0 n [ j ≤ m i n ( a i , b n − i ) ] sum_{j=1}^{∞} sum_{i=0}^n [j le min(a_i,b_{n-i})] j=1∑∞i=0∑n[j≤min(ai,bn−i)]
即 ∑ j = 1 ∞ ∑ i = 0 n [ j ≤ a i ] [ j ≤ b n − i ] sum_{j=1}^{∞} sum_{i=0}^n [j le a_i] [j le b_{n-i}] j=1∑∞i=0∑n[j≤ai][j≤bn−i]
于是我们枚举 j j j,然后令 f i = [ j ≤ a i ] , g i = [ j ≤ b i ] f_i=[j le a_i],g_i=[j le b_i] fi=[j≤ai],gi=[j≤bi]再累加 f , g f,g f,g的卷积即可。
关于这个东西的应用我们马上就会提到。
例题
T1(Luogu P6300)
Description
给定一个长度为 n n n的序列 A A A和一个数 m m m。对于每个在 [ 1 , m ] [1,m] [1,m]中的数 i i i,你需要分别回答:
⌊ lfloor ⌊ 将 A A A序列中的数两两匹配(可能会有数不在任何匹配中),满足一个匹配中两个数的和恰好等于 i i i的匹配的数量最大值 ⌉ rceil ⌉
n ≤ 1 0 5 , a i ≤ 1 0 5 n le 10^5, a_i le 10^5 n≤105, ai≤105且 m = max a i m=max {a_i} m=maxai。
Solution
令 a a a为 A A A序列的桶,即 a i = ∑ j = 1 n [ A j = i ] a_i=sum_{j=1}^n [A_j=i] ai=∑j=1n[Aj=i]。
不难发现,一次询问的答案即为 ∑ j = 0 n m i n ( a j , b i − j ) sum_{j=0}^n min(a_j,b_{i-j}) ∑j=0nmin(aj,bi−j)。这个东西我们在上面提到过,可以先枚举 j j j,然后令 f i = [ j ≤ a i ] , g i = [ j ≤ b i ] f_i=[j le a_i],g_i=[j le b_i] fi=[j≤ai],gi=[j≤bi]再累加 f , g f,g f,g的卷积得到 a n s ans ans数组。
但是这么做的时间复杂度是 O ( m 2 log m ) O(m^2 log m) O(m2logm)。
同时,我们再去考虑一个暴力做法。
我们枚举桶中的两个数 i , j i,j i,j,将 a n s i , j ans_{i,j} ansi,j加上 m i n ( a i , a j ) min(a_i,a_j) min(ai,aj)。
但是这么做的时间复杂度是 O ( m 2 ) O(m^2) O(m2)的。
考虑结合上面两种做法。
令
p
p
p为使用上述两种做法的分界点。
①根据
a
n
s
=
∑
j
=
1
∞
∑
i
=
0
n
[
j
≤
a
i
]
[
j
≤
b
n
−
i
]
ans=sum_{j=1}^{∞} sum_{i=0}^n [j le a_i] [j le b_{n-i}]
ans=∑j=1∞∑i=0n[j≤ai][j≤bn−i],我们只将
j
j
j从
1
1
1枚举到
p
p
p,剩下的
j
j
j我们暂不考虑。
②对于所有满足比
p
p
p大的
a
i
a_i
ai去暴力枚举累加贡献。
①的时间复杂度为 O ( p m log m ) O(pm log m) O(pmlogm),②的时间复杂度为 O ( ( n p ) 2 ) O((frac n p)^2) O((pn)2)。为什么②的时间复杂度是 O ( ( n p ) 2 ) O((frac n p)^2) O((pn)2)呢?因为这里的 a a a是一个桶,若 a i a_i ai比 p p p大,那么对应的,序列中 i i i出现的次数超过了 p p p。而序列中一共只有 n n n个数,所以满足比 p p p大的 a i a_i ai的级别只有 O ( n p ) O(frac n p) O(pn)。
于是总时间复杂度为 O ( p m log m + ( n p ) 2 ) O(p m log m+(frac n p)^2) O(pmlogm+(pn)2)。令 m m m与 n n n同阶,解方程
p n log n = ( n p ) 2 p n log n=(frac n p)^2 pnlogn=(pn)2
解得 p = n log n p=sqrt {frac n {log n}} p=lognn
而由于卷积的复杂度较大,我们取 p = n log n 2 p=frac {sqrt {frac n {log n}}} 2 p=2lognn时实现是相对最优。
于是时间复杂度为 O ( n log n ) O(n log n) O(nlogn)。
T2(Luogu P3338)
Description
Solution
令
a
i
=
q
i
,
b
i
=
(
1
i
)
2
a_i=q_i,b_i=(frac 1 i)^2
ai=qi,bi=(i1)2,则有
E
j
=
∑
i
=
1
j
−
1
q
i
b
j
−
i
−
∑
i
=
j
+
1
n
q
i
b
i
−
j
E_j=sum_{i=1}^{j-1} q_ib_{j-i}-sum_{i=j+1}^{n} q_i b_{i-j}
Ej=i=1∑j−1qibj−i−i=j+1∑nqibi−j
对于右式的前半部分,显然是一个关于“和”的卷积,直接NTT即可;而后半部分是一个关于“差”的卷积,按照本文开头所述的方法,我们需要翻转之后再求一遍卷积。
时间复杂度为 O ( n log n ) O(n log n) O(nlogn)。注意精度控制。
T3(Luogu P3321)
Description
Solution
由于FFT只能处理关于“和”的卷积,所以我们先考虑化加为乘,这样会对问题起到极大的简化作用。
令在模意义下的底数为 b a s e base base。于是,我们就可以将问题转化为: 将给定的序列中的每一个数 a i a_i ai变成模意义下的 b a s e a i base^{a_i} baseai,请问能够生成多少个序列,使得这个序列各项之和在模意义下为 log b a s e x log_{base} x logbasex。
现在的问题就十分简单了:处理出原序列的桶,令桶为多项式的各项系数;我们做 ∣ S ∣ |S| ∣S∣次循环卷积,答案即为 x X x^{X} xX( x x x是形式幂级数, X X X为给定的值)项的系数。
我们直接多项式快速幂即可。本题得到完美解决!
正当你代码写完之后,发现……
当 b a s e base base取得不好的时候会出现像哈希冲突一样的玩意儿。比如 m o d = 6 , b a s e = 2 mod=6,base=2 mod=6,base=2时, 2 3 ≡ 2 1 ( m o d 6 ) 2^3 equiv 2^1(mod 6) 23≡21(mod 6);也就是说, 2 2 2既可以表示为 2 2 2也可以表示为 4 4 4,这样导致了答案的不正确。
于是,你得出了以下结论——
⌊ lfloor ⌊ 这个 b a s e base base需要满足 b a s e 1 ⋯ b a s e m o d − 1 base^1 cdots base^{mod-1} base1⋯basemod−1互不相同,也就是说真数 [ 1 , 2 ⋯ m o d − 1 ] [1,2 cdots mod-1] [1,2⋯mod−1]与底数 [ 1 , 2 ⋯ m o d − 1 ] [1,2 cdots mod-1] [1,2⋯mod−1]需一一对应。 ⌉ rceil ⌉
这时恍然大悟的你发现了, b a s e base base事实上就是 m o d mod mod的原根。
于是我们套用原根的板子得到 b a s e base base,然后在模意义下转化数组与限制并多项式快速幂即可。
总时间复杂度为 O ( n + m log m ) O(n+m log m) O(n+mlogm)。
最后
以上就是单薄豌豆为你收集整理的多项式学习笔记[三](全网最详细!有图有代码有解释有例题有总结!)多项式乘法的一些小Trick例题的全部内容,希望文章能够帮你解决多项式学习笔记[三](全网最详细!有图有代码有解释有例题有总结!)多项式乘法的一些小Trick例题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复