欧拉定理及扩展

  • 本篇很多推论基于质数唯一分解定理,请读者先行了解。

欧拉函数

定义

有两种:

  1. 定义欧拉函数 φ(x) 表示小于 x 且与 x 互质的数的个数,定义 1 与任何数互质。

  2. 定义剩余类 cimodx=i 的数的集和,即所有 a%x=ia。一般可以用其中的一个 a 代表。

    由于 gcd(a,x)=gcd(x,a%x) ,所以剩余类中的数和 xgcd 都是一样的。这代表了只要剩余类中有一个数和 x 互质,这个剩余类中的所有数都与 x 互质。

    定义缩剩余类 是与 x 互质的数所在的剩余类。所有的缩剩余类组成缩系,一般可以从每个缩剩余类中选一个数来组成一个数列代表缩系。

    定义欧拉函数 φ(x)modx 的缩剩余类个数。

性质

建议读者仔细品味欧拉函数的两个定义,下面的证明将从这两方面思考。

  1. 对于质数 p φ(p)=p1 。显然成立。

  2. 对于质数 pφ(pk)=pkpk1pk 只与 p 的整数倍不互质。pk 以内 一共有 pkpp 的倍数。

  3. 任意大于 2 的数 nφ(n) 是偶数。因为 gcd(n,x)=gcd(x,nx) (不会可以在本人博客找到证明),所以与 n 互质的数都是成对出现的。

  4. 欧拉函数的积性 :(这个证法有点弱,有用 CRT 证明其通项再来证明这个的)

    对于互质的两个数 m , n ,有 φ(mn)=φ(m)φ(n)

    证明:

    将问题分成两个子问题

    xin 的一个缩剩余类,yim 的一个缩剩余类。

    1. 证明可以用 xim+yin 来表示 mn 的的一个缩剩余类,且不会重复。
    2. 证明 mn 的所有缩剩余类都可以用 xim+yin 表示。

    这样就可以证明积性

    下面来证明这些子问题:

    Ⅰ.

    first : 证明 xim+yinmn 的的一个缩剩余类

    gcd(m,n)=1(更相减损)gcd(xi,n)=1gcd(mxi,n)=1gcd(mxi+nyi,n)=1(1)gcd(yi,m)=1gcd(nyi,m)=1gcd(nyi+mxi,m)=1gcd(nyi+mxi,mn)=1

    证毕。

    second :证明xim+yin 不会重复表示一个缩剩余类

    反证法:

    xkm+yknxim+yinφ(mn)xkm+yknxim+yin(modmn)xkm+yknxim+yin(modm)yknyin(modm)yk=yixk=xi

    与假设矛盾,所以xim+yin 不会重复表示一个剩余类。

    Ⅱ.

    Zmn 的一个缩剩余类中的元素。

    (裴蜀定理) x0m+y0n=1Zx0m+Zy0n=Zmq+np=Zgcd(mq+np,mn)=1gcd(mq+np,n)=1gcd(mq,n)=1gcd(m,n)=1gcd(q,n)=1

    所以 qn 的缩剩余系中的元素,同理 pm 的缩剩余系中的元素。即所有的 mn 的缩剩余类都可以用xim+yin 表示。

  5. 欧拉函数的通项式:

    φ(m)=m(11p1)(11p2)(11pk) 其中 km 的质因子。

    证明:

    根据唯一分解定理,我们知道任意数 m 可以表示为:p1a1p2a2pkak

    由于 p 是质数, 所以φ(piai)=piaipiai1=piai(11pi) (见条目 2.)。而质因子的幂彼此互质,所以

φ(m)=φ(p1a1)φ(p2a2)φ(pkak)=m(11p1)(11p2)(11pk)

  1. 小于 n 且与其互质的数之和为 φ(n)2×n 。由于 gcd 我们知道小于 n 且和 n 互质的数是成对出现的,且两两相加为 n 。于是易得。

  2. 欧拉反演(等会了再补)

如何求欧拉函数

通项公式

根据欧拉函数的通项,我们可以质因数分解一个数,同时求其欧拉函数值。

int get_euler_1(int x){
	int ret=x;
	for(int i=2;i*i<=x;i++){
		if(x%i == 0){
			ret=ret/i*(i-1);
			while(x%i == 0){
				x/=i;
			}
		}
	} 
	if(x>1) ret=ret/x*(x-1);
	return ret;
}

线性求法

欧拉函数是积性函数,有如下性质:

  1. 质数 p 的欧拉函数值为 p1

  2. 互质两数 abφ(ab)=φ(a)×φ(b)

  3. 对于 ap ,如果 pa 的质因子,φ(ap)=p×φ(a)

这样我们就能在线性筛素数时求欧拉函数。

int get_euler_2(int x){
	inp[0]=inp[1]=1;
	for(int i=2;i<=x;i++){
		if(!inp[i]){
			phi[i]=i-1;
			prime[++tot]=i;
		}
		for(int j=1;j<=tot && prime[j]*i<=x;j++){
			int tp=prime[j]*i;
			inp[tp]=1;
			if(i%prime[j] == 0){
				phi[tp]=phi[i]*prime[j];
				break;
			}
			phi[tp]=phi[i]*phi[prime[j]];
		}
	}
	return phi[x];
}

欧拉定理

定义

对于互质的两数 am

aφ(m)1(modm)

证明

r1,r2,,rφ(m)m 的缩剩余系,由于 am 互质,ar1,ar2,,arφ(m) 也是 m 的缩剩余系。那么:

r1r2rφ(m)aφ(m)r1r2rφ(m)(modm)aφ(m)1(modm)

可以看出, m 是质数时 φ(m)=m1 ,即费马小定理。

代码

直接看拓欧吧。没有欧拉的板子。

扩展欧拉定理

定义

ab{ab%φ(m)gcd(a,m)=1abgcd(a,m)1&bφ(m)ab%φ(m)+φ(m)gcd(a,m)1&b>φ(m)(mod m)

证明

首先,我们可以简化一下问题。

我们要证

abab%φ(m)+φ(m)(modm) 

a 质因数分解,得:

ab=p1r1p2r2pkrk

对于与 m 互质的 pi ,显然有 pib=pibφ(m)+φ(m)(modp) (欧拉定理)。

那么只要证明了对于和 m 不互质的 pi 也有此性质,就有:

ab=(p1r1p2r2pkrk)b=(p1b)r1(p2b)r2(pkb)rk=(p1b%φ(m)+φ(m))r1(p2b%φ(m)+φ(m))r2(pkb%φ(m)+φ(m))rk=(p1r1p2r2pkrk)b%φ(m)+φ(m)(modm)

于是问题就简化成了求 m 的一个质因子 p 满足 pbpb%φ(m)+φ(m)

证明如下:

  • m 分解成 pks ,由于 ps 互质。就有:

    pφ(s)1(mods)

    又因为 ab(mod s)&cd(mod s)acbd(mod s) (想不通为什么可以从同余定义角度思考)。

    我们可以得出 px×φ(s)1(mods)

    又因为欧拉函数是积性函数,所以 φ(s)φ(m)

    就可以得出 pφ(m)1pφ(s)(mods)

  • 继续推:

pφ(s)1(mods)pφ(s)=x×s+1pφ(s)+k=x×s×pk+pkpφ(s)+k=xm+pkpφ(s)+kpk(modm)

又因为 pφ(m)pφ(s)(modm) ,所以 pφ(m)+kpk(modm)

  • 由此可知有:

    pbpbkpkpbk+φ(m)+kpb+φ(m)(modm)

    条件是 bk

    这时又有一个推论: 对于m=pqs ,有φ(m)q

    先单独考虑质因子 pq ,即证明φ(pq)=pq1(p1)q ,当 p=2 时为 pq1q

    首先 q=2 时成立。然后对于 q>2 的情况,我们假设 q12q1q1 成立:

    2q=2×2q12×q2

    由于 q>2 所以 2qq ,当且仅当 q=2 时取等。

    又因为 pq1(q1) 是个增函数,p 增大时就显然成立。

    那么就有 bkφ(m) 。即函数成立条件为 bφ(m)

  • 我们要将 b 尽量变小,即减去尽量多的 φ(m) 。而上面的函数可表示为:

    pxpx+φ(m)(modm) ,那么将 xφ(m) 代入 x 就有 pxφ(m)px(modp) 。注意这时定义域为 xφ(m)φ(m)x2φ(m)

    我们不可能一个一个地减去 φ(m) 最好的做法是取模,然而这样不能保证 x2φ(m)

    于是我们要再加上一个 φ(m) 。即有 pbpb%φ(m)+φ(m)(modm)b2φ(m)

    bφ(m)2φ(m) 之间时这么做也没有区别,我也不知道为什么要分在第三类中大概是好记

证毕

好长。

code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef int int_;
#define int long long  

char bb[20000050];
int aa,m,bbb;
int phi,ans;

int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
}

void exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
	}
	else{
		exgcd(b,a%b,y,x);
		y-=(a/b)*x;
	}
}

int getphi(int x){
	int ret=1;
	for(int i=2;i*i<=x && x!=1;i++){
		if(x%i != 0) continue;
		ret *=  i-1;
		x/=i;
		while(x%i==0){
			ret*=i;
			x/=i;
		}
	}
	if(x>1) ret*=x-1;
	return ret;
}

int ksm(int x,int q,int p){
	int ret=1;
	while(q>0){
		if(q&1) ret=(ret*x)%p;
		x=(x*x)%p;
		q>>=1;
	}
	return ret;
}

int_ main()
{
	bool flag=false;
	scanf("%lld %lld %s",&aa,&m,bb);
	phi=getphi(m);
	int len=strlen(bb);
	for(int i=0;i<len;i++){
		bbb=bbb*10+(int)(bb[i]-'0');
		if(bbb>=phi){
			bbb%=phi;
			flag=true;
		}
	}
	if(flag) ans=ksm(aa,bbb+phi,m);
	else ans=ksm(aa,bbb,m);
	printf("%lld",ans);
	return 0;
}

部分证明思路来源:


-EOF-
posted @   T_horn  阅读(828)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
点击右上角即可分享
微信分享提示