【学习笔记】欧拉降幂

tech2024-07-02  77

0.概述

用来解决幂取模的问题。

1.定理

1.1.基础版

a , p a,p a,p 互质时,我们有

a φ ( p ) ≡ 1 ( m o d p ) a^{\varphi(p)}\equiv 1\pmod{p} aφ(p)1(modp)

理由是,称所有与 p p p 互质的数组成的集合为 S S S(即 S = { x ∈ [ 1 , p ] ∣ gcd ⁡ ( x , p ) = 1 } S=\{x\in[1,p]\big|\gcd(x,p)=1\} S={x[1,p]gcd(x,p)=1}),则

{ r a   m o d   p ∣ r ∈ S } = S \{ra\bmod p\big|r\in S\}=S {ramodprS}=S

因为 gcd ⁡ ( r a , p ) = 1 \gcd(ra,p)=1 gcd(ra,p)=1 且两两不同。若 r 1 a ≡ r 2 a r_1a\equiv r_2a r1ar2a r 1 ≡ r 2 ( m o d p ) r_1\equiv r_2\pmod{p} r1r2(modp) ,而这是荒谬的。

于是

∏ r ∈ S ( r a ) ≡ ∏ r ∈ S r ( m o d p ) \prod_{r\in S}(ra)\equiv\prod_{r\in S}r\pmod{p} rS(ra)rSr(modp)

左式显然等于 a φ ( p ) ∏ r ∈ S r a^{\varphi(p)}\prod_{r\in S}r aφ(p)rSr ,因为 S S S 的大小是 φ ( p ) \varphi(p) φ(p) 。于是乎

a φ ( p ) ∏ r ∈ S r ≡ ∏ r ∈ S r ( m o d p ) a^{\varphi(p)}\prod_{r\in S}r\equiv\prod_{r\in S}r\pmod{p} aφ(p)rSrrSr(modp)

∏ r ∈ S r \prod_{r\in S}r rSr p p p 互质,可以消去。剩下的就是

a φ ( p ) ≡ 1 ( m o d p ) a^{\varphi(p)}\equiv 1\pmod{p} aφ(p)1(modp)

1.2.升级版

对于任意 a , p , x ( φ ( p ) ≤ x ) a,p,x(\varphi(p)\le x) a,p,x(φ(p)x) 满足

a x ≡ a x   m o d   φ ( p ) ⋅ a φ ( p ) ( m o d p ) a^{x}\equiv a^{x\bmod\varphi(p)}\cdot a^{\varphi(p)}\pmod{p} axaxmodφ(p)aφ(p)(modp)

理由是精妙的。首先说明这一点:对于任意质数 p p p 和正整数 q q q 满足 φ ( p q ) ≥ q \varphi(p^q)\ge q φ(pq)q 。构造法即可:此 q q q 个数为 p i − 1 p^i-1 pi1 i i i 1 , 2 , 3 , … , q 1,2,3,\dots,q 1,2,3,,q 就恰好有 q q q 个)。然后小分类讨论:

互质的情况。

gcd ⁡ ( a , p ) = 1 \gcd(a,p)=1 gcd(a,p)=1 时,就是 1.1.基础版 的情形,故成立。

不互质的情况。

p p p 只有一个质因子时,设 p = q k p=q^k p=qk ,因为 gcd ⁡ ( a , p ) ≠ 1 \gcd(a,p)\ne 1 gcd(a,p)=1 ,所以 a a a 也同样含有此质因子。而 x ≥ φ ( p ) = φ ( q k ) ≥ k x\ge\varphi(p)=\varphi(q^k)\ge k xφ(p)=φ(qk)k ,所以 q k ∣ a x q^k|a^x qkax 。所以

a x ≡ 0 ( m o d p ) a^x\equiv 0\pmod{p} ax0(modp)

这是对 ∀ x ≥ φ ( p ) \forall x\ge\varphi(p) xφ(p) 都成立的。而 x   m o d   φ ( p ) + φ ( p ) x\bmod \varphi(p)+\varphi(p) xmodφ(p)+φ(p) 显然也是一个合法的 x x x 取值。于是

a x ≡ a x   m o d   φ ( p ) ⋅ a φ ( p ) ( m o d p ) a^{x}\equiv a^{x\bmod\varphi(p)}\cdot a^{\varphi(p)}\pmod{p} axaxmodφ(p)aφ(p)(modp)

其实两边都是零,蠢透了。

p p p 不只有一个质因子时,设 p = q 1 k 1 q 2 k 2 ⋯ q n k n p=q_1^{k_1}q_2^{k_2}\cdots q_n^{k_n} p=q1k1q2k2qnkn 为其质因数分解,记 p i = q i k i p_i=q_i^{k_i} pi=qiki 。由于 x ≥ φ ( p ) ≥ φ ( p i ) x\ge\varphi(p)\ge\varphi(p_i) xφ(p)φ(pi) ,肯定有

a x ≡ a x   m o d   φ ( p i ) ⋅ a φ ( p i ) ( m o d p i ) a^{x}\equiv a^{x\bmod\varphi(p_i)}\cdot a^{\varphi(p_i)}\pmod{p_i} axaxmodφ(pi)aφ(pi)(modpi)

而这个式子的本质是什么?是 a φ ( p i ) ≡ a 2 φ ( p i ) a^{\varphi(p_i)}\equiv a^{2\varphi(p_i)} aφ(pi)a2φ(pi) 。没看出来充分,至少看出来其必要。

两边都变成原来的 ∏ j ≠ i φ ( p j ) \prod_{j\ne i}\varphi(p_j) j=iφ(pj) 次方,取模意义下等式仍成立。故

a φ ( p ) ≡ a 2 φ ( p ) ( m o d p i ) a^{\varphi(p)}\equiv a^{2\varphi(p)}\pmod{p_i} aφ(p)a2φ(p)(modpi)

因为 ∏ j = 1 n φ ( p j ) = φ ( p ) \prod_{j=1}^{n} \varphi(p_j)=\varphi(p) j=1nφ(pj)=φ(p) ,积性函数嘛。

注意到 x , y x,y x,y 如果在模 a a a 和模 b b b 意义下都相等,那二者在模 lcm ( a , b ) \text{lcm}(a,b) lcm(a,b) 意义下亦相等。于是得到

a φ ( p ) ≡ a 2 φ ( p ) ( m o d p ) a^{\varphi(p)}\equiv a^{2\varphi(p)}\pmod{p} aφ(p)a2φ(p)(modp)

而上式是充分的,自行验证不难。结论即是开头的式子。

2.例题

2.1.板题

2.1.1.题目

C a l c u l a t i o n \tt Calculation Calculation:定义 f ( n ) = ( n   m o d   10 ) f ( ⌊ n 10 ⌋ ) f(n)=(n\bmod 10)^{f(\lfloor\frac{n}{10}\rfloor)} f(n)=(nmod10)f(10n) ,边界为 f ( 0 ) = 1 f(0)=1 f(0)=1 ,求 f ( n )   m o d   m f(n)\bmod m f(n)modm n , m ≤ 1 0 9 n,m\le 10^9 n,m109

2.1.2.思路

显然唯一问题就是 f f f 的值很大。利用欧拉降幂即可。怎么判断 f ( n ) f(n) f(n) 的指数是否超过了 φ ( m ) \varphi(m) φ(m) 呢?

注意到 a φ ( p ) ≡ a 2 φ ( p ) a^{\varphi(p)}\equiv a^{2\varphi(p)} aφ(p)a2φ(p) 这个式子中,两边的值明显不同(除非 a ≤ 1 a\le 1 a1 ,因为 φ ( p ) = 0 \varphi(p)=0 φ(p)=0 恒不成立)。如果要相等,则右式一定超过了模数。故

a 2 φ ( p ) ≥ p a^{2\varphi(p)}\ge p a2φ(p)p

注意 a φ ( p ) ≥ p a^{\varphi(p)}\ge p aφ(p)p 未必成立。比如 φ ( 6 ) = 2 \varphi(6)=2 φ(6)=2 就会被 a = 2 a=2 a=2 绝杀。

于是用 f ( n , m ) f(n,m) f(n,m) 表示 f ( n ) f(n) f(n) (题面中的那个)取模 m m m 的值。 g ( n , m ) g(n,m) g(n,m) 表示 f ( n ) f(n) f(n) 是否不小于 m m m 。有递推式

f ( n , m ) = ( n   m o d   10 ) f [ ⌊ n 10 ⌋ , φ ( m ) ] + g [ ⌊ n 10 ⌋ , φ ( m ) ] ⋅ φ ( m )   m o d   m f(n,m)=(n\bmod 10)^{f\big[\lfloor\frac n{10}\rfloor,\varphi(m)\big]+g\big[\lfloor\frac n{10}\rfloor,\varphi(m)\big]\cdot\varphi(m)}\bmod m f(n,m)=(nmod10)f[10n,φ(m)]+g[10n,φ(m)]φ(m)modm

g ( n , m ) = f ( n , m ) ∨ g [ ⌊ n 10 ⌋ , 2 φ ( m ) ] g(n,m)=f(n,m)\vee g\left[\left\lfloor\frac n{10}\right\rfloor,2\varphi(m)\right] g(n,m)=f(n,m)g[10n,2φ(m)]

第二个式子中的 f ( n , m ) f(n,m) f(n,m) 大家都懂的,就是计算过程中超过了 m m m 就行。但是两个式子的递归情况不同,比较烦。因为我们必须保证 g ( n , m ) g(n,m) g(n,m) 中涵盖了两种情况——递归中取模了;未取模,幂时爆了。

但是我们有妙招:在 g ( n , 2 m ) = 1 g(n,2m)=1 g(n,2m)=1 时, f ( n , m ) + g ( n , m ) ⋅ m = f ( n , 2 m )   m o d   m + m f(n,m)+g(n,m)\cdot m=f(n,2m)\bmod m+m f(n,m)+g(n,m)m=f(n,2m)modm+m ;在 g ( n , 2 m ) = 0 g(n,2m)=0 g(n,2m)=0 时, f ( n , m ) + g ( n , m ) ⋅ m = f ( n , 2 m ) f(n,m)+g(n,m)\cdot m=f(n,2m) f(n,m)+g(n,m)m=f(n,2m)

所以 f ( n , m ) f(n,m) f(n,m) 的方程式中的指数可以被完全表示出来了,只递归 2 φ ( m ) 2\varphi(m) 2φ(m) 的情况即可。

2.1.3.代码

#include <cstdio> #include <iostream> #include <vector> using namespace std; typedef long long int_; inline int readint(){ int a = 0; char c = getchar(), f = 1; for(; c<'0'||c>'9'; c=getchar()) if(c == '-') f = -f; for(; '0'<=c&&c<='9'; c=getchar()) a = (a<<3)+(a<<1)+(c^48); return a*f; } int_ getphi(int_ n){ int_ res = n; for(int i=2; i<=n/i; ++i) if(n%i == 0){ res = res/i*(i-1); while(!(n%i)) n /= i; } if(n > 1) res = res/n*(n-1); return res; } int_ mul(int_ a,int_ b,int_ c){ // int_ sysl = (a*b-(int_)((long double)a/c*b+1e-8)*c)%c; // if(sysl < 0) sysl += c; return sysl; int_ ans = 0; if(a < b) swap(a,b); for(; b; b>>=1,a=(a<<1)%c) if(b&1) ans = (ans+a)%c; return ans; } bool over; // 是否超出过 m int_ qkpow(int_ bas,int_ q,int_ m){ int_ ans = 1; bool zxy = 0; for(; q; q>>=1){ if(q&1){ if(bas && ans > (m-1)/bas) over = true; if(zxy) over = true; ans = mul(ans,bas,m); } if(bas && bas > (m-1)/bas) zxy = true; bas = mul(bas,bas,m); } return ans; } int_ f(int n,int_ m){ if(n == 0){ over = 0; // 多组数据! return 1; // 题面中的规定 } if(n%10 == 1){ over = 0; return 1; } if(!(n%10)){ if(f(n/10,m) || over){ over = 0; return 0; } return 1; // 0^0 = 1 } int_ phi = getphi(m); int_ x = f(n/10,phi<<1); if(over) x = x%phi+phi; return qkpow(n%10,x,m); } int main(){ int T, n, m; for(scanf("%d",&T); T; --T){ scanf("%d %d",&n,&m); printf("%lld\n",f(n,m)); } return 0; }

2.1.4.后记

搜到的题解中还有另一种做法,就是认为 a φ ( p ) ≥ p a^{\varphi(p)}\ge p aφ(p)p ,故而直接求 f ( n , m ) + g ( n , m ) ⋅ m f(n,m)+g(n,m)\cdot m f(n,m)+g(n,m)m 的值, g g g 只在计算幂时考虑,不递推。

为什么这是对的呢?因为 我太敏感一来就找到反例 只有 2 φ ( 6 ) < 6 2^{\varphi(6)}<6 2φ(6)<6 。只有 6 6 6 能做到!

如果要构造反例,则需要 φ ( p ) = 6 \varphi(p)=6 φ(p)=6 ,故 p ∈ { 7 , 9 , 14 , 18 } p\in\{7,9,14,18\} p{7,9,14,18} 。但这几个模数都无法构造出反例。

所以究竟为什么只有 6 满足这个式子啊,淦。

有些题解是完全错误的,只需要试试 f ( 253 )   m o d   36 f(253)\bmod 36 f(253)mod36 就能找出问题。答案应当为 27 27 27

这道题中的 0 0 = 1 0^0=1 00=1 的规定也非常不友好。我因为这一条 W A \tt WA WA 了十几发。

2.2.狗题

2.2.1.题目

相逢是问候:区间修改, a ′ = a c a'=a^c a=ac ;区间查询 ∑ a \sum a a 。这里的 c c c 是固定不变的,即,每次修改操作都是同一个 c c c 1 ≤ n , m ≤ 5 × 1 0 4 , 1 ≤ c < p ≤ 1 0 8 1\le n,m\le 5\times 10^4,1\le c<p\le 10^8 1n,m5×104,1c<p108

2.2.2.思路

不难发现一个数就会变成 c c c a c^{c^{c^a}} ccca 。当层数够大,足以让 a a a 无用时(某一层的 φ = 1 \varphi=1 φ=1 了),这个数就不会变。用并查集去找到每一个没有“堆叠够高”的数字并暴力修改。每个数字会被修改 O ( log ⁡ p ) \mathcal O(\log p) O(logp) 次。由于每次都要重新将数字塔拆开(或者你存储当前数字的 O ( log ⁡ p ) \mathcal O(\log p) O(logp) 种余数),所以一次修改需要做 O ( log ⁡ p ) \mathcal O(\log p) O(logp) c y c^y cy 的工作。没办法,只好使用光速乘。

总复杂度 O ( n log ⁡ 2 p + n log ⁡ p log ⁡ n + p + m log ⁡ n ) \mathcal O(n\log^2p+n\log p\log n+\sqrt p+m\log n) O(nlog2p+nlogplogn+p +mlogn) 。并查集的复杂度我也不太清楚,我按照 m log ⁡ n m\log n mlogn 算的。

2.2.3.代码

然后咕掉了。

最新回复(0)