转置原理
**线性算法:**有一个 n × n n\times n n×n的矩阵 M M M,输入一个 n n n维向量 a a a,计算 b = M a b=Ma b=Ma的过程叫线性算法。
具体的,若一个算法只包含以下三种操作,那么其就是线性算法:
- x ← x + c y x\leftarrow x+cy x←x+cy
- s w a p ( x , y ) swap(x,y) swap(x,y)
- x ← c x x\leftarrow cx x←cx
**线性算法的转置:**对于一个计算 b = M a b=Ma b=Ma的线性算法,其转置就是输入 b b b,计算 a = M T b a=M^{T}b a=MTb。
转置原理是指:若我们能在一定时间复杂度内完成一个线性算法,那么一定能在同样的时间复杂度内完成其转置。
我们将 M M M分解成一系列初等矩阵 M = E 1 E 2 ⋯ E r M=E_1E_2\cdots E_r M=E1E2⋯Er,那么 M T = E r T E r − 1 T ⋯ E 1 T M^{T}=E_r^{T}E_{r-1}^T\cdots E_1^T MT=ErTEr−1T⋯E1T。
因此转置一个算法就是将原算法倒着执行,同时每一个基本运算都进行转置。
一些例子
DFT的转置:
D F T DFT DFT本质是乘上了一个范德蒙德矩阵,其是对称的,因此其转置就是本身。
这个可以用来去掉蝴蝶变换。
加法卷积的转置:
将 H = F × G H=F\times G H=F×G中的 F F F看成输入, G G G看成常量,那么 H k = ∑ i = 0 G k − i F i H_k=\sum_{i=0}G_{k-i}F_i Hk=∑i=0Gk−iFi。
那么 H = A F H=AF H=AF的矩阵为 A i , j = [ i ≥ j ] G i − j A_{i,j}=[i\geq j]G_{i-j} Ai,j=[i≥j]Gi−j
即转置后为
H
′
=
A
T
F
H'=A^TF
H′=ATF,有:
H
k
′
=
∑
i
=
0
A
k
,
i
T
F
i
=
∑
i
=
0
A
i
,
k
F
i
=
∑
i
=
k
G
i
−
k
F
i
=
∑
i
=
0
G
i
F
i
+
k
\begin{aligned} H_k'=\sum_{i=0}A^T_{k,i}F_i=\sum_{i=0}A_{i,k}F_i=\sum_{i=k}G_{i-k}F_i=\sum_{i=0}G_iF_{i+k} \end{aligned}
Hk′=i=0∑Ak,iTFi=i=0∑Ai,kFi=i=k∑Gi−kFi=i=0∑GiFi+k
即减法卷积,下面记为
×
T
\times ^T
×T。
多点求值
原多点求值算法为考虑 F ( x 0 ) = F ( x ) m o d ( x − x 0 ) F(x_0)=F(x)\bmod (x-x_0) F(x0)=F(x)mod(x−x0),以此分治做多项式取模,常数较大。
我们将多点求值写成矩阵相乘的形式:
(
f
(
a
1
)
⋮
f
(
a
n
)
)
=
(
1
a
1
⋯
a
1
n
−
1
⋮
⋱
⋱
⋮
1
⋯
⋯
a
n
n
−
1
)
(
f
0
⋮
f
n
−
1
)
\begin{pmatrix}f(a_1)\\\vdots\\f(a_n)\end{pmatrix}=\begin{pmatrix}1&a_1&\cdots&a_1^{n-1 }\\\vdots&\ddots&\ddots&\vdots\\1&\cdots&\cdots &a_n^{n-1}\end{pmatrix}\begin{pmatrix}f_0\\\vdots\\f_{n-1}\end{pmatrix}
⎝⎜⎛f(a1)⋮f(an)⎠⎟⎞=⎝⎜⎛1⋮1a1⋱⋯⋯⋱⋯a1n−1⋮ann−1⎠⎟⎞⎝⎜⎛f0⋮fn−1⎠⎟⎞
其转置即为:
(
1
⋯
1
a
1
⋯
a
n
⋮
⋱
⋮
a
1
n
−
1
⋯
a
n
n
−
1
)
(
g
1
⋮
g
n
)
\begin{pmatrix}1&\cdots&1\\a_1&\cdots&a_n\\\vdots&\ddots&\vdots\\a_1^{n-1}&\cdots &a_n^{n-1}\end{pmatrix}\begin{pmatrix}g_1\\\vdots\\g_{n}\end{pmatrix}
⎝⎜⎜⎜⎛1a1⋮a1n−1⋯⋯⋱⋯1an⋮ann−1⎠⎟⎟⎟⎞⎝⎜⎛g1⋮gn⎠⎟⎞
=最后第
i
i
i项为
∑
j
=
1
n
g
j
a
j
i
=
∑
j
=
1
n
g
j
[
x
i
]
1
1
−
a
j
x
=
[
x
i
]
∑
j
=
1
n
g
j
1
−
a
j
x
\sum_{j=1}^ng_ja_j^i=\sum_{j=1}^n g_j\ [x^i]\dfrac{1}{1-a_jx}=[x^i]\sum_{j=1}^n\dfrac{g_j}{1-a_jx}
∑j=1ngjaji=∑j=1ngj [xi]1−ajx1=[xi]∑j=1n1−ajxgj
这个是较为简单的,我们分治时维护当前区间答案为 A ( x ) B ( x ) \dfrac{A(x)}{B(x)} B(x)A(x),合并左右区间即 A l ( x ) B r ( x ) + A r ( x ) B l ( x ) B l ( x ) B r ( x ) \dfrac{A_{l}(x)B_{r}(x)+A_{r}(x)B_{l}(x)}{B_l(x)B_r(x)} Bl(x)Br(x)Al(x)Br(x)+Ar(x)Bl(x)
注意,整个算法中 g g g为输入,因此 B B B是个常多项式,可以预先预处理,同时转置算法时我们不需要转置它。
我们完整的描述一下这个算法:
-
首先预处理 B B B,然后开始分治
-
向左右区间分治
-
计算 A l ( x ) B r ( x ) , A r ( x ) B l ( x ) A_{l}(x)B_{r}(x),A_{r}(x)B_{l}(x) Al(x)Br(x),Ar(x)Bl(x)并相加
-
最后根上的多项式乘 B [ 1 , n ] B_{[1,n]} B[1,n]即所求
将其转置:
- 预处理 B B B,将传入的多项式 A A A转置乘 B [ 1 , n ] ( x ) − 1 B_{[1,n]}(x)^{-1} B[1,n](x)−1
- 将信息下传, A r = A × T B l , A l = A × T B r A_r=A\times^TB_l,A_l=A\times^TB_r Ar=A×TBl,Al=A×TBr
- 不断分治,最后到叶子都是常数项,即所求的点值。
整个过程只需要一次求逆即可。
例题
有 n n n件物品,第 i i i件物品属性为 p i p_i pi。
主人公等级初始为 0 0 0,使用第 i i i件物品会有 p i p_i pi的概率让等级加一, 1 − p i 1-p_i 1−pi 的概率不变。
若最后等级为 j j j,则会具有 a j a_j aj 的攻击力。
令 f i f_i fi 表示使用除 i i i外的 n − 1 n-1 n−1个物品后的期望攻击力。要求求出 f 1 , f 2 , ⋯ , f n f_1,f_2, \cdots ,f_n f1,f2,⋯,fn。答案对 998244353 998244353 998244353 取模。
n ≤ 1 0 5 n\leq 10^5 n≤105
给出长为 n n n的序列 a , b , c a,b,c a,b,c,对于 k ∈ [ 1 , n ] k\in [1,n] k∈[1,n]求出:
∑ i = 1 n ( c i ∏ j = 1 k ( a i + b j ) ) \sum_{i=1}^n(c_i\prod_{j=1}^k(a_i+b_j)) i=1∑n(cij=1∏k(ai+bj))
n ≤ 2.5 × 1 0 5 n\leq 2.5\times 10^5 n≤2.5×105,时限 10 s 10s 10s
记
F
i
(
x
)
=
∏
j
=
1
i
(
x
+
b
j
)
F_i(x)=\prod_{j=1}^i(x+b_j)
Fi(x)=∏j=1i(x+bj),将上式转化为矩阵的形式:
(
[
x
0
]
F
1
(
x
)
⋯
[
x
n
]
F
1
(
x
)
[
x
0
]
F
2
(
x
)
⋯
[
x
n
]
F
2
(
x
)
⋮
⋱
⋮
[
x
0
]
F
n
(
x
)
⋯
[
x
n
]
F
n
(
x
)
)
(
a
1
0
⋯
a
n
0
a
1
1
⋯
a
n
2
⋮
⋱
⋮
a
1
n
⋯
a
n
n
)
(
c
1
c
2
⋮
c
n
)
\begin{pmatrix}[x^0]F_1(x)& \cdots&[x^n]F_1(x)\\ [x^0]F_2(x)& \cdots&[x^n]F_2(x)\\\vdots&\ddots&\vdots\\ [x^0]F_n(x)& \cdots&[x^n]F_n(x)\end{pmatrix}\begin{pmatrix}a_1^0& \cdots& a_n^0\\ a_1^1& \cdots&a_n^2\\\vdots&\ddots&\vdots\\ a_1^n& \cdots&a_n^n\end{pmatrix}\begin{pmatrix}c_1\\c_2\\\vdots\\c_n\end{pmatrix}
⎝⎜⎜⎜⎛[x0]F1(x)[x0]F2(x)⋮[x0]Fn(x)⋯⋯⋱⋯[xn]F1(x)[xn]F2(x)⋮[xn]Fn(x)⎠⎟⎟⎟⎞⎝⎜⎜⎜⎛a10a11⋮a1n⋯⋯⋱⋯an0an2⋮ann⎠⎟⎟⎟⎞⎝⎜⎜⎜⎛c1c2⋮cn⎠⎟⎟⎟⎞
右边两个即
∑
i
=
1
n
c
i
1
−
a
i
x
\sum_{i=1}^n\dfrac{c_i}{1-a_ix}
∑i=1n1−aixci,分治fft计算即可,下面记为
f
f
f
剩下的我们用转置原理,考虑转置后求的是什么: a n s i = [ x i ] ∑ j = 1 n F j ( x ) f j ans_i=[x_i]\sum_{j=1}^n F_j(x)f_j ansi=[xi]∑j=1nFj(x)fj
这个可以分治fft解决,记 F l , r = ∏ i = l r ( x + b i ) , A l , r = ∑ i = l r f i F l , i ( x ) F_{l,r}=\prod_{i=l}^r(x+b_i),A_{l,r}=\sum_{i=l}^rf_iF_{l,i}(x) Fl,r=∏i=lr(x+bi),Al,r=∑i=lrfiFl,i(x)
F F F与 f f f无关,可以先预处理。 A l , r = A l , m i d + A m i d + 1 , r F l , r A_{l,r}=A_{l,mid}+A_{mid+1,r}F_{l,r} Al,r=Al,mid+Amid+1,rFl,r
叶子为 f i × ( x + b i ) f_i\times(x+b_i) fi×(x+bi)
再将其转置回去,这个流程为:
- 初始 A 1 , n = f A_{1,n}=f A1,n=f,同时预处理 F F F
- A l = A , A r = A × T F l A_{l}=A,A_r=A\times^T F_l Al=A,Ar=A×TFl
- 递归左右儿子,最后到叶子时 a n s i = A × T ( x + b i ) ans_i=A\times^T(x+b_i) ansi=A×T(x+bi),即 [ x 0 ] A ⋅ b i + [ x 1 ] A [x^0]A\cdot b_i+[x^1]A [x0]A⋅bi+[x1]A
简单函数的复合
若 G ( x ) G(x) G(x)是一个简单函数,那么我们能在较少的时间内算出 F ( G ( x ) ) m o d x n F(G(x))\bmod x^{n} F(G(x))modxn
我们认为简单函数有下面几种:
1.加法
F ( x + k ) = ∑ i = 0 n − 1 F i ( x + k ) i = ∑ i = 0 n − 1 F i ∑ j = 0 i ( i j ) x j k i − j = ∑ j = 0 n − 1 x j j ! ∑ i = j n − 1 F i ⋅ i ! k i − j ( i − j ) ! F(x+k)=\sum_{i=0}^{n-1}F_i(x+k)^i=\sum_{i=0}^{n-1}F_i\sum_{j=0}^i\binom{i}{j}x^jk^{i-j}=\sum_{j=0}^{n-1}\frac{x^j}{j!}\sum_{i=j}^{n-1}F_i\cdot i!\frac{k^{i-j}}{(i-j)!} F(x+k)=i=0∑n−1Fi(x+k)i=i=0∑n−1Fij=0∑i(ji)xjki−j=j=0∑n−1j!xji=j∑n−1Fi⋅i!(i−j)!ki−j
一次卷积即可。
2.乘法
F ( k x ) F(kx) F(kx),线性乘一边即可。
3.幂
F ( x k ) F(x^k) F(xk),下标变换
4.逆元
有 F R ( x ) = x n − 1 F ( x − 1 ) F^{R}(x)=x^{n-1}F(x^{-1}) FR(x)=xn−1F(x−1),那么 F ( x − 1 ) = F R ( x ) × x 1 − n F(x^{-1})=F^R(x)\times x^{1-n} F(x−1)=FR(x)×x1−n
一次求逆即可。
5.开 k k k次根
设
x
x
x对应后面的幂级数是
g
g
g,且
g
=
h
k
g=h^k
g=hk。我们将
F
F
F的下标按模
k
k
k分类:
F
i
(
x
)
=
∑
j
F
j
k
+
i
x
j
F_i(x)=\sum_j F_{jk+i} x^j
Fi(x)=j∑Fjk+ixj
那么有:
F
(
h
)
=
∑
i
F
i
(
g
)
h
i
F(h)=\sum_i F_i(g)h^i
F(h)=i∑Fi(g)hi
求出
h
h
h后将其拼起来即可。
6.指数
F ( e x ) = ∑ i = 0 n − 1 F i e i x = ∑ i = 0 n − 1 F i ∑ j i j j ! x j = ∑ j x j j ! ∑ i F i i j F(e^x)=\sum_{i=0}^{n-1}F_ie^{ix}=\sum_{i=0}^{n-1}F_i\sum_j \frac{i^j}{j!}x^j=\sum_j \frac{x^j}{j!}\sum_iF_ii^j F(ex)=i=0∑n−1Fieix=i=0∑n−1Fij∑j!ijxj=j∑j!xji∑Fiij
考虑计算:
∑
j
x
j
∑
i
F
i
i
j
\sum_jx^j\sum_{i}F_ii^j
j∑xji∑Fiij
这个就是刚才多点求值的转置。
7.对数
直接不好考虑,我们考虑复合指数的逆,复合指数可以描述为对 F F F进行多点求值的转置,然后每个位置乘 1 j ! \frac{1}{j!} j!1,将其转置就是先乘 1 j ! \frac{1}{j!} j!1,在进行多点求值,其逆就是多点插值后每个位置乘 j ! j! j!,在将这个算法转置回去即可。
用途
我们考虑一个线性变换 M a = b Ma=b Ma=b,考虑 M M M对应的二元生成函数 F ( x , y ) F(x,y) F(x,y),若其可以表示为 u ( x ) v ( y ) f ( g ( x ) h ( y ) ) u(x)v(y)f(g(x)h(y)) u(x)v(y)f(g(x)h(y))其中 g , h g,h g,h为常数个简单函数复合而成,那么我们可以快速计算 M a Ma Ma
先假设
u
=
v
=
1
u=v=1
u=v=1,那么有:
M
i
,
j
=
∑
k
g
i
k
f
k
h
j
k
a
n
s
i
=
∑
j
a
j
∑
k
g
i
k
f
k
h
j
k
M_{i,j}=\sum_kg_i^kf_kh^k_j\\ ans_i=\sum_ja_j\sum_kg_i^kf_kh^k_j
Mi,j=k∑gikfkhjkansi=j∑ajk∑gikfkhjk
即三个线性变换的复合
g
g
g复合,点乘
f
f
f,
h
h
h复合的转置。
加上 u , v u,v u,v后原线性变换变为三个线性变换的复合:乘 u u u,原线性变换,乘 v v v的转置
随机游走
在一个无穷大的二维平面上,一个人出发点是 ( 0 , 0 ) (0, 0) (0,0),每步可以沿向量 ( 1 , 1 ) (1, 1) (1,1)$(1, 0) 和 和 和(2, 0)$走,分别带有 1 , a , b 1, a, b 1,a,b 的权值;
此人随时可以停止。若停在 ( x , y ) (x, y) (x,y),则会产生 w y w_y wy的权值;
定义一条路径的权是这些权值的乘积。对于 a ∈ [ 1 , n ] a\in[1,n] a∈[1,n],求出结束在 x x x坐标为 a a a的所有点的所有路径权值之和 g a g_a ga。n ≤ 1 0 5 n\leq 10^5 n≤105,对 998244353 998244353 998244353取模
令 f x , y f_{x,y} fx,y表示到达 x , y x, y x,y的路径权值和, f 0 , 0 = 1 f_{0,0}=1 f0,0=1,有 f i , j = f i − 1 , j − 1 + a f i − 1 , j + b f i − 2 , j f_{i,j}=f_{i-1,j-1}+af_{i-1,j}+bf_{i-2,j} fi,j=fi−1,j−1+afi−1,j+bfi−2,j
最后 g a = ∑ y f a , y w y g_a=\sum_yf_{a,y}w_y ga=∑yfa,ywy
令
f
f
f的二元生成函数为
F
(
x
,
y
)
F(x,y)
F(x,y),那么有:
F
=
1
+
x
y
F
+
a
x
F
+
b
x
2
F
F=1+xyF+axF+bx^2F
F=1+xyF+axF+bx2F,可解得:
F
=
1
1
−
(
a
+
y
)
x
−
x
2
=
1
(
1
−
x
2
)
(
1
−
a
+
y
1
−
x
2
)
F=\frac{1}{1-(a+y)x-x^2}=\frac{1}{(1-x^2)(1-\frac{a+y}{1-x^2})}
F=1−(a+y)x−x21=(1−x2)(1−1−x2a+y)1
写成上面的形式即可。