【学习笔记】欧拉降幂

0.概述

用来解决幂取模的问题。

1.定理

1.1.基础版

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

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

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

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

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

于是

r S ( r a ) r S r ( m o d p ) \prod_{r\in S}(ra)\equiv\prod_{r\in S}r\pmod{p}

左式显然等于 a φ ( p ) r S r a^{\varphi(p)}\prod_{r\in S}r ,因为 S S 的大小是 φ ( p ) \varphi(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}

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

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

1.2.升级版

对于任意 a , p , x ( φ ( p ) x ) a,p,x(\varphi(p)\le 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}

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

  1. 互质的情况。

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

  1. 不互质的情况。

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

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

这是对 x φ ( p ) \forall x\ge\varphi(p) 都成立的。而 x m o d φ ( p ) + φ ( p ) x\bmod \varphi(p)+\varphi(p) 显然也是一个合法的 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}

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

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 i = q i k i p_i=q_i^{k_i} 。由于 x φ ( p ) φ ( p i ) x\ge\varphi(p)\ge\varphi(p_i) ,肯定有

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}

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

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

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

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

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

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

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

2.例题

2.1.板题

2.1.1.题目

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

2.1.2.思路

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

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

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

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

于是用 f ( n , m ) f(n,m) 表示 f ( n ) f(n) (题面中的那个)取模 m m 的值。 g ( n , m ) g(n,m) 表示 f ( n ) f(n) 是否不小于 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

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]

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

但是我们有妙招:在 g ( n , 2 m ) = 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 ;在 g ( n , 2 m ) = 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 ) f(n,m) 的方程式中的指数可以被完全表示出来了,只递归 2 φ ( m ) 2\varphi(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 ,故而直接求 f ( n , m ) + g ( n , m ) m f(n,m)+g(n,m)\cdot m 的值, g g 只在计算幂时考虑,不递推。

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

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

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

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

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

猜你喜欢

转载自blog.csdn.net/qq_42101694/article/details/108391478