简介
与莫反类似,单位根反演是一个可以表示 [ n ∣ k ] [n\mid k] [ n ∣ k ] 的式子,由此推出的一系列应用:
1 n ∑ i = 0 n − 1 ω n k i = [ n ∣ k ] \frac{1}{n}\sum_{i=0}^{n-1}\omega_n^{ki}=[n\mid k]
n 1 i = 0 ∑ n − 1 ω n ki = [ n ∣ k ]
当 n ∣ k n\mid k n ∣ k 时,根据单位根的定义 ω n k = exp ( 2 π i k n ) = 1 \omega_n^k=\exp(2\pi i\frac{k}{n})=1 ω n k = exp ( 2 πi n k ) = 1 ,此时原式为 1 1 1 ;当 n ∤ k n\not\mid k n ∣ k 时根据等比数列求和公式得到:
1 n ∑ i = 0 n − 1 ( ω n k ) i = 1 n 1 − ω n n k 1 − ω n k \frac{1}{n}\sum_{i=0}^{n-1}(\omega_n^k)^i=\frac{1}{n}\frac{1-\omega_n^{nk}}{1-\omega_n^k}
n 1 i = 0 ∑ n − 1 ( ω n k ) i = n 1 1 − ω n k 1 − ω n nk
同样根据 ω n n k = exp ( 2 π i n k n ) = 1 \omega_n^{nk}=\exp(2\pi i\frac{nk}{n})=1 ω n nk = exp ( 2 πi n nk ) = 1 ,而 ω n k ≠ 1 \omega_n^k\ne 1 ω n k = 1 ,因此原式值为 0 0 0 。
FFT
回顾 FFT,对于一个 n − 1 n-1 n − 1 次的多项式 F ( x ) F(x) F ( x ) ,当我们知道 ( ω n i , F ( ω n i ) ) (\omega_n^i,F(\omega_n^i)) ( ω n i , F ( ω n i )) 时,想根据这个求出所有 [ x k ] F ( x ) [x^k]F(x) [ x k ] F ( x ) ,可以写成这样:
[ x k ] F ( x ) = ∑ j = 0 n − 1 [ j = k ] [ x j ] F ( x ) = ∑ j = 0 n − 1 [ n ∣ ( j − k ) ] [ x j ] F ( x ) = ∑ j = 0 n − 1 ( 1 n ∑ i = 0 n − 1 ω n ( j − k ) i ) [ x j ] F ( x ) = 1 n ∑ j = 0 n − 1 ∑ i = 0 n − 1 [ x j ] F ( x ) ω n ( j − k ) i = 1 n ∑ j = 0 n − 1 ∑ i = 0 n − 1 [ x j ] F ( x ) ω n i j ω n − k i = 1 n ∑ i = 0 n − 1 F ( ω n i ) ω n − k i = 1 n ∑ i = 0 n − 1 F ( ω n i ) ( ω n − k ) i \begin{aligned}
\text{[}x^k]F(x)&=\sum_{j=0}^{n-1}[j=k][x^j]F(x)\\
&=\sum_{j=0}^{n-1}[n\mid (j-k)][x^j]F(x)\\
&=\sum_{j=0}^{n-1}\left(\frac{1}{n}\sum_{i=0}^{n-1}\omega_n^{(j-k)i}\right)[x^j]F(x)\\
&=\frac{1}{n}\sum_{j=0}^{n-1}\sum_{i=0}^{n-1}[x^j]F(x)\omega_n^{(j-k)i}\\
&=\frac{1}{n}\sum_{j=0}^{n-1}\sum_{i=0}^{n-1}[x^j]F(x)\omega_n^{ij}\omega_n^{-ki}\\
&=\frac{1}{n}\sum_{i=0}^{n-1}F(\omega_n^i)\omega_{n}^{-ki}\\
&=\frac{1}{n}\sum_{i=0}^{n-1}F(\omega_n^i)(\omega_n^{-k})^i
\end{aligned}
[ x k ] F ( x ) = j = 0 ∑ n − 1 [ j = k ] [ x j ] F ( x ) = j = 0 ∑ n − 1 [ n ∣ ( j − k )] [ x j ] F ( x ) = j = 0 ∑ n − 1 ( n 1 i = 0 ∑ n − 1 ω n ( j − k ) i ) [ x j ] F ( x ) = n 1 j = 0 ∑ n − 1 i = 0 ∑ n − 1 [ x j ] F ( x ) ω n ( j − k ) i = n 1 j = 0 ∑ n − 1 i = 0 ∑ n − 1 [ x j ] F ( x ) ω n ij ω n − ki = n 1 i = 0 ∑ n − 1 F ( ω n i ) ω n − ki = n 1 i = 0 ∑ n − 1 F ( ω n i ) ( ω n − k ) i
也就是 [ x k ] F ( x ) [x^k]F(x) [ x k ] F ( x ) 的值是以 F ( ω n i ) F(\omega_n^i) F ( ω n i ) 为 [ x i ] G ( x ) [x^i]G(x) [ x i ] G ( x ) 求 G ( ω n − k ) G(\omega_n^{-k}) G ( ω n − k ) ,而 DFT 的过程就是在求一个多项式在 ω n k \omega_n^k ω n k 处的值,因此 IDFT 可以复用 DFT 的代码,只需要把 ω n k \omega_n^k ω n k 换成 ω n − k \omega_n^{-k} ω n − k 最后再乘一下 1 n \frac{1}{n} n 1 即可。
用模 p p p 的原根 g n k = g ( p − 1 ) k n g_n^k=g^{(p-1)\frac{k}{n}} g n k = g ( p − 1 ) n k 来代替单位根可以避免精度问题。
LJJ 学二项式定理
给定 n , s , a 0 ∼ a 3 n,s,a_0\sim a_3 n , s , a 0 ∼ a 3 其中 n n n 范围 1 0 18 10^{18} 1 0 18 ,其它 1 0 8 10^8 1 0 8 。求:
( ∑ i = 0 n ( n i ) s i a i m o d 4 ) m o d 998244353 \left(\sum_{i=0}^n\binom{n}{i}s^ia_{i\bmod 4}\right)\bmod 998244353
( i = 0 ∑ n ( i n ) s i a i mod 4 ) mod 998244353
题目链接:LOJ6485 。
考虑枚举 i m o d 4 = k i\bmod 4=k i mod 4 = k ,而 [ i m o d 4 = k ] = [ 4 ∣ ( i − k ) ] [i\bmod 4=k]=[4\mid (i-k)] [ i mod 4 = k ] = [ 4 ∣ ( i − k )] ,把同余条件转化为整除条件然后代入单位根反演的式子:
∑ i = 0 n ( n i ) s i a i m o d 4 = ∑ k = 0 3 ∑ i = 0 n ( n i ) s i a k [ i m o d 4 = k ] = ∑ k = 0 3 ∑ i = 0 n ( n i ) s i a k [ 4 ∣ ( i − k ) ] = 1 4 ∑ k = 0 3 ∑ j = 0 3 ∑ i = 0 n ( n i ) s i ω 4 j ( i − k ) a k = 1 4 ∑ k = 0 3 ∑ j = 0 3 ( a k ω 4 − k j ∑ i = 0 n ( n i ) s i ω 4 j i ) = 1 4 ∑ k = 0 3 ∑ j = 0 3 a k ω 4 − k j ( s ω 4 j + 1 ) n \begin{aligned}
\sum_{i=0}^n\binom{n}{i}s^ia_{i\bmod 4}&=\sum_{k=0}^3\sum_{i=0}^n\binom{n}{i}s^ia_k[i\bmod 4=k]\\
&=\sum_{k=0}^3\sum_{i=0}^n\binom{n}{i}s^ia_k[4\mid (i-k)]\\
&=\frac{1}{4}\sum_{k=0}^3\sum_{j=0}^3\sum_{i=0}^n\binom{n}{i}s^i\omega_4^{j(i-k)}a_k\\
&=\frac{1}{4}\sum_{k=0}^3\sum_{j=0}^3\left(a_k\omega_4^{-kj}\sum_{i=0}^n\binom{n}{i}s^i\omega_4^{ji}\right)\\
&=\frac{1}{4}\sum_{k=0}^3\sum_{j=0}^3a_k\omega_4^{-kj}(s\omega_4^j+1)^n\\
\end{aligned}
i = 0 ∑ n ( i n ) s i a i mod 4 = k = 0 ∑ 3 i = 0 ∑ n ( i n ) s i a k [ i mod 4 = k ] = k = 0 ∑ 3 i = 0 ∑ n ( i n ) s i a k [ 4 ∣ ( i − k )] = 4 1 k = 0 ∑ 3 j = 0 ∑ 3 i = 0 ∑ n ( i n ) s i ω 4 j ( i − k ) a k = 4 1 k = 0 ∑ 3 j = 0 ∑ 3 ( a k ω 4 − kj i = 0 ∑ n ( i n ) s i ω 4 ji ) = 4 1 k = 0 ∑ 3 j = 0 ∑ 3 a k ω 4 − kj ( s ω 4 j + 1 ) n
单组询问复杂度 O ( log n ) O(\log n) O ( log n ) ,有 16 16 16 的常数,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <bits/stdc++.h> using namespace std;#define int long long const int P = 998244353 , I4 = 748683265 ;int T, n, s, a[4 ];int qmi (int a, int k) { int res = 1 ; while (k) { if (k & 1 ) res = res * a % P; a = a * a % P; k >>= 1 ; } return res; } signed main () { cin >> T; while (T--) { cin >> n >> s >> a[0 ] >> a[1 ] >> a[2 ] >> a[3 ]; int res = 0 ; for (int k = 0 ; k < 4 ; k++) { int w = qmi (3 , (P-1 )/4 ), negwk = qmi (3 , P-1 -((P-1 )/4 *k)); for (int j = 0 , w1 = 1 , w2 = 1 ; j < 4 ; j++, w1 = w1 * negwk % P, w2 = w2 * w % P) { res = (res + a[k] * w1 % P * qmi ((s * w2 + 1 ) % P, n)) % P; } } cout << res * I4 % P << endl; } return 0 ; }
[洛谷月赛] 小猪佩奇学数学
给定 n , p , k n,p,k n , p , k 满足 1 ≤ n , p < 998244353 , k ∈ { 2 w ∣ 0 ≤ w ≤ 20 } 1\le n,p\lt 998244353,k\in\{2^w|0\le w\le 20\} 1 ≤ n , p < 998244353 , k ∈ { 2 w ∣0 ≤ w ≤ 20 } 问:
∑ i = 0 n ( n i ) p i ⌊ i k ⌋ m o d 998244353 \sum_{i=0}^n\binom{n}{i}p^i\lfloor\frac{i}{k}\rfloor\bmod 998244353
i = 0 ∑ n ( i n ) p i ⌊ k i ⌋ mod 998244353
题目链接:P5591 。
根据模的定义,可以将原式子拆成两个部分:
∑ i = 0 n ( n i ) p i ⌊ i k ⌋ = 1 k ∑ i = 0 n ( n i ) i p i − 1 k ∑ i = 0 n ( n i ) p i ( i m o d k ) \begin{aligned}
\sum_{i=0}^n\binom{n}{i}p^i\lfloor\frac{i}{k}\rfloor&=\frac{1}{k}\sum_{i=0}^n\binom{n}{i}ip^i-\frac{1}{k}\sum_{i=0}^n\binom{n}{i}p^i(i\bmod k)
\end{aligned}
i = 0 ∑ n ( i n ) p i ⌊ k i ⌋ = k 1 i = 0 ∑ n ( i n ) i p i − k 1 i = 0 ∑ n ( i n ) p i ( i mod k )
对于左半部分,根据组合数的性质有:
1 k ∑ i = 0 n ( n i ) i p i = n p k ∑ i = 1 n ( n − 1 i − 1 ) p i − 1 = n p ( p + 1 ) n − 1 k \frac{1}{k}\sum_{i=0}^n\binom{n}{i}ip^i=\frac{np}{k}\sum_{i=1}^n\binom{n-1}{i-1}p^{i-1}=\frac{np(p+1)^{n-1}}{k}
k 1 i = 0 ∑ n ( i n ) i p i = k n p i = 1 ∑ n ( i − 1 n − 1 ) p i − 1 = k n p ( p + 1 ) n − 1
对于右半部分,同样是枚举 i m o d k i\bmod k i mod k 的值:
1 k ∑ r = 0 k − 1 ∑ i = 0 n ( n i ) p i r [ i m o d k = r ] = 1 k ∑ r = 0 k − 1 ∑ i = 0 n ( n i ) p i r [ k ∣ ( i − r ) ] = 1 k 2 ∑ r = 0 k − 1 ∑ i = 0 n ( n i ) p i r ∑ j = 0 k − 1 ω k ( i − r ) j = 1 k 2 ∑ r = 0 k − 1 ∑ j = 0 k − 1 ∑ i = 0 n ( n i ) p i r ω k i j ω k − r j = 1 k 2 ∑ r = 0 k − 1 ∑ j = 0 k − 1 r ω k − r j ∑ i = 0 n ( n i ) p i ω k i j = 1 k 2 ∑ j = 0 k − 1 ( p ω k j + 1 ) n ∑ r = 0 k − 1 r ω k − r j \begin{aligned}
\frac{1}{k}\sum_{r=0}^{k-1}\sum_{i=0}^n\binom{n}{i}p^ir[i\bmod k=r]&=\frac{1}{k}\sum_{r=0}^{k-1}\sum_{i=0}^n\binom{n}{i}p^ir[k\mid(i-r)]\\
&=\frac{1}{k^2}\sum_{r=0}^{k-1}\sum_{i=0}^n\binom{n}{i}p^ir\sum_{j=0}^{k-1}\omega_k^{(i-r)j}\\
&=\frac{1}{k^2}\sum_{r=0}^{k-1}\sum_{j=0}^{k-1}\sum_{i=0}^n\binom{n}{i}p^ir\omega_k^{ij}\omega_{k}^{-rj}\\
&=\frac{1}{k^2}\sum_{r=0}^{k-1}\sum_{j=0}^{k-1}r\omega_{k}^{-rj}\sum_{i=0}^n\binom{n}{i}p^i\omega_k^{ij}\\
&=\frac{1}{k^2}\sum_{j=0}^{k-1}(p\omega_k^j+1)^n\sum_{r=0}^{k-1}r\omega_{k}^{-rj}\\
\end{aligned}
k 1 r = 0 ∑ k − 1 i = 0 ∑ n ( i n ) p i r [ i mod k = r ] = k 1 r = 0 ∑ k − 1 i = 0 ∑ n ( i n ) p i r [ k ∣ ( i − r )] = k 2 1 r = 0 ∑ k − 1 i = 0 ∑ n ( i n ) p i r j = 0 ∑ k − 1 ω k ( i − r ) j = k 2 1 r = 0 ∑ k − 1 j = 0 ∑ k − 1 i = 0 ∑ n ( i n ) p i r ω k ij ω k − r j = k 2 1 r = 0 ∑ k − 1 j = 0 ∑ k − 1 r ω k − r j i = 0 ∑ n ( i n ) p i ω k ij = k 2 1 j = 0 ∑ k − 1 ( p ω k j + 1 ) n r = 0 ∑ k − 1 r ω k − r j
对于后边这个等差乘等比,这里推一个结论,错位相减法。
S n = ∑ i = 1 n − 1 i q i q S n = ∑ i = 2 n ( i − 1 ) q i ( 1 − q ) S n = − ( n − 1 ) q n + ∑ i = 1 n − 1 q i S n = ( 1 − n ) q n 1 − q + q ( 1 − q n − 1 ) ( 1 − q ) 2 = q − q n + ( 1 − q ) ( 1 − n ) q n ( 1 − q ) 2 = q − n q n + ( n − 1 ) q n + 1 ( 1 − q ) 2 \begin{aligned}
S_n&=\sum_{i=1}^{n-1}iq^i\\
qS_n&=\sum_{i=2}^{n}(i-1)q^{i}\\
(1-q)S_n&=-(n-1)q^n+\sum_{i=1}^{n-1}q^i\\
S_n&=\frac{(1-n)q^n}{1-q}+\frac{q(1-q^{n-1})}{(1-q)^2}\\
&=\frac{q-q^n+(1-q)(1-n)q^n}{(1-q)^2}\\
&=\frac{q-nq^n+(n-1)q^{n+1}}{(1-q)^2}
\end{aligned}
S n q S n ( 1 − q ) S n S n = i = 1 ∑ n − 1 i q i = i = 2 ∑ n ( i − 1 ) q i = − ( n − 1 ) q n + i = 1 ∑ n − 1 q i = 1 − q ( 1 − n ) q n + ( 1 − q ) 2 q ( 1 − q n − 1 ) = ( 1 − q ) 2 q − q n + ( 1 − q ) ( 1 − n ) q n = ( 1 − q ) 2 q − n q n + ( n − 1 ) q n + 1
当然 q = 1 q=1 q = 1 时原式等于 n ( n − 1 ) 2 \frac{n(n-1)}{2} 2 n ( n − 1 ) ,这个只能特判。带入得到:
1 k 2 ∑ j = 0 k − 1 ( p ω k j + 1 ) n ∑ r = 0 k − 1 r ω k − r j = 1 k 2 ∑ j = 0 k − 1 ( p ω k j + 1 ) n S k , ω k − j \begin{aligned}
\frac{1}{k^2}\sum_{j=0}^{k-1}(p\omega_k^j+1)^n\sum_{r=0}^{k-1}r\omega_{k}^{-rj}&=\frac{1}{k^2}\sum_{j=0}^{k-1}(p\omega_k^j+1)^nS_{k,\omega_k^{-j}}
\end{aligned}
k 2 1 j = 0 ∑ k − 1 ( p ω k j + 1 ) n r = 0 ∑ k − 1 r ω k − r j = k 2 1 j = 0 ∑ k − 1 ( p ω k j + 1 ) n S k , ω k − j
懒得根据单位根性质化简 S k S_k S k 了,反正能 O ( 1 ) O(1) O ( 1 ) 求出来,代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <bits/stdc++.h> using namespace std;#define int long long const int P = 998244353 , I2 = 499122177 ;int n, p, k;int qmi (int a, int k = P-2 ) { int res = 1 ; while (k) { if (k & 1 ) res = res * a % P; a = a * a % P; k >>= 1 ; } return res; } int S (int n, int q) { if (q == 1 ) return n * (n-1 ) % P * I2 % P; int res = (q - n * qmi (q, n) + (n-1 ) * qmi (q, n+1 )) % P; res = res * qmi ((1 -q) * (1 -q) % P) % P; return (res + P) % P; } signed main () { cin >> n >> p >> k; int r1 = n * p % P * qmi (p+1 , n-1 ) % P * qmi (k) % P; int r2 = 0 ; int wk = qmi (3 , (P-1 ) / k), wkn = qmi (wk); for (int j = 0 , wj = 1 , wjn = 1 ; j < k; j++, wj = wj * wk % P, wjn = wjn * wkn % P) { r2 = (r2 + qmi ((p * wj + 1 ) % P, n) * S (k, wjn)) % P; } int ans = ((r1 - r2 * qmi (k * k % P)) % P + P) % P; cout << ans << endl; return 0 ; }
[BZOJ3328] PYXFIB
给定 n , k , p n,k,p n , k , p 其中 n ≤ 1 0 18 , k ≤ 2 × 1 0 4 , p ≤ 1 0 9 n\le 10^{18},k\le 2\times 10^4,p\le 10^9 n ≤ 1 0 18 , k ≤ 2 × 1 0 4 , p ≤ 1 0 9 且 p p p 为质数,保证 p m o d k = 1 p\bmod k=1 p mod k = 1 ,求:
∑ i = 0 ⌊ n k ⌋ ( n i k ) f i k \sum_{i=0}^{\lfloor\frac{n}{k}\rfloor}\binom{n}{ik}f_{ik}
i = 0 ∑ ⌊ k n ⌋ ( ik n ) f ik
其中 f 0 = f 1 = 1 f_0=f_1=1 f 0 = f 1 = 1 ,对于 n ≥ 2 n\ge 2 n ≥ 2 有 f n = f n − 1 + f n − 2 f_n=f_{n-1}+f_{n-2} f n = f n − 1 + f n − 2 。
题目链接:P10664 。
首先转化一下,写成单位根反演可以做的式子:
∑ i = 0 n [ k ∣ i ] ( n i ) f i = ∑ i = 0 n ( 1 k ∑ j = 0 k − 1 ω k i j ) ( n i ) f i = 1 k ∑ i = 0 n ∑ j = 0 k − 1 ( n i ) f i ω k i j \begin{aligned}
\sum_{i=0}^n[k\mid i]\binom{n}{i}f_i&=\sum_{i=0}^n\left(\frac{1}{k}\sum_{j=0}^{k-1}\omega_{k}^{ij}\right)\binom{n}{i}f_i\\
&=\frac{1}{k}\sum_{i=0}^n\sum_{j=0}^{k-1}\binom{n}{i}f_i\omega_{k}^{ij}
\end{aligned}
i = 0 ∑ n [ k ∣ i ] ( i n ) f i = i = 0 ∑ n ( k 1 j = 0 ∑ k − 1 ω k ij ) ( i n ) f i = k 1 i = 0 ∑ n j = 0 ∑ k − 1 ( i n ) f i ω k ij
对于斐波那契和组合数乘一块的情况,在 JLCPC2024 C 中也有出现,这里是我写的题解 。总之就是由于斐波那契的转移矩阵 A A A 和单位阵 E E E 具有交换律,因此可以对矩阵用二项式定理。接着推:
1 k ∑ j = 0 k − 1 ∑ i = 0 n ( n i ) A i F 0 ω k i j = 1 k ∑ j = 0 k − 1 ∑ i = 0 n ( n i ) ( A ω k j ) i E n − i F 0 = 1 k ∑ j = 0 k − 1 ( A ω k j + E ) n F 0 \begin{aligned}
\frac{1}{k}\sum_{j=0}^{k-1}\sum_{i=0}^n\binom{n}{i}A^iF_0\omega_{k}^{ij}&=\frac{1}{k}\sum_{j=0}^{k-1}\sum_{i=0}^n\binom{n}{i}(A\omega_k^j)^iE^{n-i}F_0\\
&=\frac{1}{k}\sum_{j=0}^{k-1}(A\omega_k^j+E)^nF_0
\end{aligned}
k 1 j = 0 ∑ k − 1 i = 0 ∑ n ( i n ) A i F 0 ω k ij = k 1 j = 0 ∑ k − 1 i = 0 ∑ n ( i n ) ( A ω k j ) i E n − i F 0 = k 1 j = 0 ∑ k − 1 ( A ω k j + E ) n F 0
这样就可以做到 O ( k log n ) O(k\log n) O ( k log n ) 解决了。对于单位根,由于题目保证 p m o d k = 1 p\bmod k=1 p mod k = 1 ,因此 ω k j ≡ g j k ( p − 1 ) ( m o d p ) \omega_k^j\equiv g^{\frac{j}{k}(p-1)}\pmod p ω k j ≡ g k j ( p − 1 ) ( mod p ) ,需要找出来一个原根。这里用原根是为了保证当 k ≢ 0 ( m o d φ ( p ) ) k\not\equiv 0\pmod{\varphi(p)} k ≡ 0 ( mod φ ( p )) 时有 g k ≢ 1 ( m o d p ) g^k\not\equiv 1\pmod p g k ≡ 1 ( mod p ) ,否则单位根反演的式子就不成立了。
由于最小原根大概是 O ( p 1 4 ) O(p^{\frac{1}{4}}) O ( p 4 1 ) 的,原根的充要条件是 δ p ( g ) = φ ( p ) \delta_p(g)=\varphi(p) δ p ( g ) = φ ( p ) 。对于任意 g g g ,由于 δ p ( g ) \delta_p(g) δ p ( g ) 保证 a 0 , a 1 , … , a δ p ( g ) − 1 a^0,a^1,\dots,a^{\delta_p(g)-1} a 0 , a 1 , … , a δ p ( g ) − 1 互不相同,所以一定有 δ p ( g ) ∣ φ ( p ) \delta_p(g)\mid \varphi(p) δ p ( g ) ∣ φ ( p ) ,直接用 φ ( p ) \varphi(p) φ ( p ) 的所有因子 d d d 验证是否有 g d ≡ 1 ( m o d p ) g^d\equiv 1\pmod p g d ≡ 1 ( mod p ) 即可。如果存在 d ∣ φ ( p ) d\mid \varphi(p) d ∣ φ ( p ) 使得 g d ≡ 1 ( m o d p ) g^d\equiv 1\pmod p g d ≡ 1 ( mod p ) ,那么 d d d 的倍数一定也满足条件,所以直接枚举 φ ( p ) / p i \varphi(p)/p_i φ ( p ) / p i 即可,其中 p i p_i p i 为 φ ( p ) \varphi(p) φ ( p ) 的质因子。
所以质因数分解 φ ( p ) \varphi(p) φ ( p ) ,这里的复杂度大概是 O ( p ) O(\sqrt p) O ( p ) 。然后枚举原根,验证的复杂度不计。找到原根后,复杂度为 O ( k log n ) O(k\log n) O ( k log n ) 。单次复杂度为 O ( p + k log n ) O(\sqrt p+k\log n) O ( p + k log n ) ,可以通过。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #include <bits/stdc++.h> using namespace std;#define eb emplace_back #define int long long int T, n, k, p, g;vector<int > fac; int qmi (int a, int k) { int res = 1 ; while (k) { if (k & 1 ) res = res * a % p; a = a * a % p; k >>= 1 ; } return res; } struct Matrix { int dat[2 ][2 ]; Matrix () { memset (dat, 0 , sizeof dat); } Matrix operator *(const Matrix& mat) const { Matrix res; for (int i = 0 ; i < 2 ; i++) for (int k = 0 ; k < 2 ; k++) for (int j = 0 ; j < 2 ; j++) res.dat[i][j] = (res.dat[i][j] + dat[i][k] * mat.dat[k][j]) % p; return res; } Matrix qmi (int k) { Matrix res, a = *this ; res.dat[0 ][0 ] = res.dat[1 ][1 ] = 1 ; while (k) { if (k & 1 ) res = res * a; a = a * a; k >>= 1 ; } return res; } }; signed main () { cin >> T; while (T--) { fac.clear (); cin >> n >> k >> p; int phi = p-1 ; for (int i = 2 ; i*i <= phi; i++) { if (phi % i) continue ; while (phi % i == 0 ) phi /= i; fac.eb (i); } if (phi != 1 ) fac.eb (phi); for (g = 2 ; g < p; g++) { for (int f: fac) if (qmi (g, (p-1 ) / f) == 1 ) goto nxt; break ; nxt:; } int res = 0 , w1 = qmi (g, (p-1 ) / k); for (int w = 1 , j = 0 ; j < k; j++, w = w * w1 % p) { Matrix f; f.dat[0 ][0 ] = f.dat[0 ][1 ] = f.dat[1 ][0 ] = w; f.dat[0 ][0 ]++, f.dat[1 ][1 ]++; f = f.qmi (n); res = (res + f.dat[0 ][0 ]) % p; } cout << res * qmi (k, p-2 ) % p << endl ; } return 0 ; }