同余类、欧拉降幂

数论基础G

同余类

给定一个正整数 \(n\) ,将所有整数依据模 \(n\) 的余数 \(r\in[0,n-1]\) 分为 \(n\) 类,其中每一类都可以被表示为 \(C_r=nx+r\) ,一个 \(C_r\) 构成的一个集合是模 \(n\) 的一个同余类

完全剩余系

给定一个正整数 \(n\) ,有 \(n\) 个不同的模 \(n\) 的同余类,从这 \(n\) 个同余类中各选出一个元素共计 \(n\) 个数,这些数构成的一个集合为模 \(n\) 的一个完全剩余系。显然对于正整数 \(n\) 一定存在一个完全剩余系是 \(Z_n=[0,n-1]\) ,该剩余系为简单完全剩余系。同理,对剩余系中任意元素加上 \(n\) 的整数倍后得到的集合仍然为模 \(n\) 的一个完全剩余系

简化剩余系

给定一个正整数 \(n\) ,有 \(\varphi(n)\) 个不同的模 \(n\) 的余数 \(r\)\(n\) 互质的同余类,在这 \(\varphi(n)\) 个同余类中各选出一个元素共计 \(\varphi(n)\) 个数,这些数构成的一个集合是模 \(n\) 的一个简化剩余系。其中 \(\varphi(n)\)\(n\) 的欧拉函数

\[\varphi(n)=n\times \prod_{i=1}^s \frac{p_i-1}{p_i} \]

欧拉定理

\({\rm{gcd}}(a,m)=1\),则 \(a^{\varphi(m)} \equiv 1({\rm{mod}}\ m)\)

简单证明:

\(\{r_1,r_2,\cdots ,r_{\varphi(m)} \}\) 是一个模 \(m\) 的简化剩余系,则 \(\{ar_1,ar_2,\cdots,ar_{\varphi(m)} \}\) 也是模 \(m\) 的一个简化剩余系,所以有

\[\prod_{i=1}^{\varphi(m)} r_i\equiv \prod_{i=1}^{\varphi(m)} ar_i \equiv a^{\varphi(m)}\prod_{i=1}^{\varphi(m)} r_i ({\rm{mod }}\ m) \]

同余式两侧约去 \(\prod_{i=1}^{\varphi(m)} r_i\) 后得

\[a^{\varphi(m)} \equiv 1({\rm{mod}}\ m) \]

\(m\) 为质数时 \(\varphi(m)=m-1\) ,得到费马小定理 \(a^{m-1}\equiv 1({\rm{mod}}\ m)\)

扩展欧拉定理

\[a^b=\left\{ \begin{array}{l} a^{b\ {\rm{mod}}\ \varphi(m)} & {\rm{gcd}}(a,m)=1 &({\rm{mod}}\ m) \\ a^b&b<\varphi(m),{\rm{gcd}}(a,m)\ne1 &({\rm{mod}}\ m) \\ a^{b\ {\rm{mod}}\ \varphi(m)+\varphi(m)} &b\ge\varphi(m),{\rm{gcd}}(a,m)\ne1&({\rm{mod}}\ m) \end{array} \right. \]

计算 \(a^b\) 时,若 \(b\) 较小,直接跑一遍快速幂即可,否则先用扩展欧拉定理进行降幂再跑快速幂

对于单独的 \(b\) 来说,利用试除法比筛法更加优秀

LL get_phi(LL n){
	LL res=n;
	for (LL i=2;i*i<=n;i++){
		if (n%i==0){
			res=res*(i-1)/i;
			while (n%i==0)
				n/=i;
		}
	}
	if (n>1) res=res*(n-1)/n;
	return res;
}

\(b\) 进行降幂操作,因为 \(a^{\varphi(m)} \equiv 1\to a^{b\ {\rm{mod}}\ \varphi(m)}\equiv a^{b\ {\rm{mod}}\ \varphi(m)+\varphi(m)}({\rm{mod}}\ m)\) ,所以不需要单独判断

LL depow(LL phi,string b){
	LL res=0;
	bool f=0;//判断b和phi_m的大小关系
	for (auto c:b){
		res=res*10+(c-'0');
		if (res>=phi) f=1,res%=phi;
	}
	if (f) res+=phi;//如果b>phi_m则需要加上phi_m
	return res;
}

以洛谷P5091为例:https://www.luogu.com.cn/problem/P5091、

LL ksm(LL a,LL b,LL p){
	LL res=1;
	while (b){
		if (b&1) res=res*a%p;
		a=a*a%p;
		b>>=1;
	}
	return res;
}

LL get_phi(LL n){
	LL res=n;
	for (LL i=2;i*i<=n;i++){
		if (n%i==0){
			res=res*(i-1)/i;
			while (n%i==0)
				n/=i;
		}
	}
	if (n>1) res=res*(n-1)/n;
	return res;
}

LL depow(LL phi,string b){
	LL res=0;
	bool f=0;
	for (auto c:b){
		res=res*10+(c-'0');
		if (res>=phi) f=1,res%=phi;
	}
	if (f) res+=phi;
	return res;
}

void solve(){
	LL a,m;
	string b;
	cin>>a>>m>>b;
	cout<<ksm(a,depow(get_phi(m),b),m)<<endl;
}
posted @ 2025-07-23 15:48  才瓯  阅读(12)  评论(0)    收藏  举报