あいさか たいがblogAisaka_Taiga的博客
//https://img2018.cnblogs.com/blog/1646268/201908/1646268-20190806114008215-138720377.jpg

欧拉定理及其推论,裴蜀定理,计算欧拉函数

Toretto·2023-05-21 11:14·67 次阅读

欧拉定理及其推论,裴蜀定理,计算欧拉函数

欧拉定理#

内容:若正整数 an,互质,则 aφ(n)1(modn)

证明:设 X1,X2......Xφ(n)1nn 互质的数。

首先我们来考虑一些数:aX1,aX2.....aXφ(n)

这些数有如下两个性质:

(1)任意两个数模 n 的余数一定不同。

证明:若存在 aX1aX2(modn) 则存在 n(aX1aX2),而 an 互质,并且 (aX1aX2)<n,所以 n 不可能整除 (aX1aX2) ,也就是说不存在 aX1aX2(modn),所以对于任意的与 n 互质的 Xi 均成立。故得证。

那么因为有 φ(n) 个这样的数,Xi(modn)(i=1φ(n)) 所以就有 φ(n) 个不同的余数,并且模数分别为 (0n1)

(2)
对于任意的 aXi(modn) 都与 n 互质。这不难想,因为 an 互质是欧拉函数的条件,Xi(1n)n 互质的数的集合中的元素。所以如果 aXi 作为分子,n 作为分母,那么他们构成的显然是一个最简分数,也就是说 aXin 互质。接下来就可以用欧几里得算法:因为 gcd(aXi,n)=1 所以 gcd(aXi,n)=gcd(n,aXimodn)=1

把上面两个性质结合一下来说,aX1(modn) ,aX2(modn)....aXφ(n)(modn) 构成了一个集合(性质1已经证明了所有元素的互异性),并且这些数是 1nn 互质的所有数构成的集合(性质1已经说明)。这样,上述集合经过一定的排序后和集合 {X1,X2....Xφ(n)} 完全一一对应,那么:aX1(modn)×aX2(modn)×....×aXφ(n)(modn)=X1×X2×.....×Xφ(n)

因此我们可以写出以下式子:

aX1×aX2×....×aXφ(n)X1×X2×....×Xφ(n)(modn),

即:(aφ(n)1)×X1×X2×....×Xφ(n)0(modn)

又因为 X1×X2×....×Xφ(n)n 互质,所以 (aφ(n)1)n,那么 aφ(n)1(modn)。欧拉定理得证。

裴蜀定理#

定义:若 a,b 是整数,且 gcd(a,b)=d,那么对于任意的整数 x,y,ax+by 都一定是 d 的倍数,特别的,一定存在整数 x,y,使 ax+by=d 成立。

简单来说,我们设 d=gcd(a,b),那么对于方程 ax+by=d,一定存在一组整数解,并且对于方程 ax+by=z,如果满足 dz,那么方程一定有整数解,否则无整数解。

首先来证明一下 ax+by=d 有整数解(耐心看):

先不要去想那个式子,先来想一想怎么求 gcd(a,b)

用辗转相除法对 8

我们设 ab,由辗转相除法的过程 gcd(x,y)=gcd(y,xmody) 可以得到:

b=ax1+r1,那么 bmodab=r1

重复此过程可以得到下面的式子:

b=ax1+r1

a=r1x2+r2

.......

rk3=rk2xk1+rk1 (1)

rk2=rk1xk+rk (2)

rk1=rkxk+1+rk+1

因为辗转相除法最后得到的余数为 0 所以我们设 rk1=0,那么 rk 就是 ab 的最大公约数,即 rk=d。将 rk=d 带入(2)中得:

rk2=rk1xk+d

移项一下,得:

d=rk2rk1xk (3)

将(1)移项得:

rk1=rk3rk2xk1 (4)

将(4)带入(3)式得到:

d=rk2(rk3rk2xk1)xk

把式子展开后,可以表示成

d=rk2rk3xk+rk2xk1xk

合并一下同类项,得:

d=rk2(xk1xk+1)rk3xk

这系数有点长,换个字母代替一下:

d=m1rk2+n1rk3

简洁多了,上面所有的字母代表的都是整数,所以 m1,n1 也一定是整数。

如果把(3)表示成 d=mrk1+nrk2 的话

d=mrk1+nrk2

d=m1rk2+n1rk3

当我们将这两个式子一直像上面的做法一样一直搞下去,就可以得到(学长说就是一个不断递归的过程,自己手模一下可能会好理解一些):

d=m2rk3+n2rk4

d=m3rk4+n3rk5

......

d=mka+nkb

显然 mknk 一定是整数,故,ax+by=d 一定有整数解。

于是就有一个很重要的推论:

对于方程 ax+by=1,只有当 a,b 互质时,方程才有整数解。

有了上面的证明,这个就很容易证(本来不打算写证明了但万一有人看呢)。

证明:

a,b 不互质,那么 a,b 可以表示成 a=q×gcd(a,b),b=p×gcd(a,b),带入上面的式子,得到:

q×gcd(a,b)×x+p×gcd(a,b)×y=1

两边同时除以 gcd(a,b),得到:

qx+py=1gcd(a,b)

显然,如果此时 a,b 不互质,那么等式的右边已经成为了一个小数,那么,该方程一定不存在整数解。

故只有当整数 a,b 互质时,该方程才会有整数解。

然后,判断二元不定方程是否有整数解的方法出现了:

对于方程 ax+by=z,只有满足 gcd(a,b)z,方程才有整数解。

证明(吐了):

d=gcd(a,b),z=d×q

对于方程 ax+by=d,我们设有一组解为 x1,y1,那么就有:

ax1+by1=d

两边同时乘上 p,得到:

ax1×q+by1×q=d×q

因为 z=d×q

所以方程 ax+by=z,一定存在一组整数解为 x=x1×q,y=y1×q

然后这东西还可以扩展到 n 元不定方程上。

对于不定方程 a1x1+a2x2+a3x3+...+anxn=z,满足 gcd(a1,a2,...,an)z 时,方程才有整数解。

对于不定方程 a1x1+a2x2+a3x3+...+anxn=1,只有所有系数 a1,a2,...,an 的最大公约数为 1 时,方程才会有解。

所有系数 a1,a2,...,an 的最大公约数为 1 的充要条件是:满足不定方程 a1x1+a2x2+a3x3+...+anxn=1

终于结束了(上面的证明自己推一下就好啦)。

欧拉定理推论#

若正整数 a,n 互质,那么对于任意正整数 b,有 ababmodφ(n)(modn)

证明(跟费马小定理差不多好像):

把上面那个式子变一下形:abbmodφ(n)×abmodφ(n)abmodφ(n)(modn)(这式子真他妈难打),所以接下来只需要证明 abbmodφ(n)1(modn),又因为:(bbmodφ(n))φ(n),设 (bbmodφ(n))=q×φ(n)(q 为自然数),则有 aq×φ(n)=(aq)φ(n),因为 a,n,互质,那么 (aq)n 也互质,那么就转化到了欧拉定理:(aq)φ(n)1(modn),成立,故得证。

这个推论可以帮助我们在求幂运算的时候缩小数据范围和计算次数。具体的说:在求乘方运算时,可以先把底数对 mod 取模,再把指数对 bmodφ(n) 取模。

特别的,如果 a,mod 不互质,且 b>φ(n) 时,ababmodφ(n)+φ(n)(modn)

计算欧拉函数#

来说一下如何计算欧拉函数的值,因为做模板题被 T 痛了。

参考:自为风月马前卒

第一种方法就是直接暴力循环枚举小于等于 n 的每一个数,然后用 gcd 函数来判断是否互质,很好写,很简单,很暴力,很 TLE。

第二种方法:大约是 n 的复杂度(我不懂这个,我只在乎他会不会 T)。我们需要分情况讨论。

n=1 时,很明显是1。

n 为质数时,很明显是 n1,因为只有他自己与他不互质。

n 为合数的情况。

这个最难搞,先对 n 进行质因数分解。

n=a1p1×a2p2...akpk

假设 k=1

辣么 φ(pk)=pkpk1.

证明:

与一个数互素的数的个数就是这个数减去与他不互素的数的个数,因为 p 是素数,所以 pk 中与其不互素的数为 p,2p...pk1p,有 pk1 个,得证。

k1 时。

φ(n)=φ(a1p1×a2p2...akpk)

φ(n)=i=1kapiaipi1

φ(n)=i=1kaipi(11pi)

φ(n)=n×i=1k(11pi)

好的把 dalao 的代码放在下面:

Copy
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 1e7 + 10; int p, ans = 1, N; void GetPhi() { for(int i = 2; i * i <= p; i++) { if(p % i == 0) { int now = i - 1; p /= i; while(p % i == 0) now = now * i, p /= i; ans = ans * now; } } if(p != 1) ans *= (p - 1); } int main() { cin >> p; N = p; GetPhi(); cout << ans; return 0; }

第三种方法:线性筛。

因为欧拉函数是积性函数,因此可以用线性筛。

性质1:若 p 为素数,φ(n)=n1.

性质2:若 imodp0,且 p 为素数

φ(i×p)=φ(i)×φ(p)=φ(i×p)=φ(i)×(p1)

这一步同时利用了性质1和欧拉函数的积性。

性质3:若 imodp=0,且 p 为素数

φ(i×p)=φ(i)×p

证明就算了吧咕咕咕。

dalao 代码:

Copy
#include<bits/stdc++.h> using namespace std; const int MAXN = 3e5 + 10; void GetPhi(int N) { static int phi[MAXN], vis[MAXN], prime[MAXN], tot = 0; for(int i = 2; i <= N; i++) { if(!vis[i]) prime[++tot] = i, phi[i] = i - 1; for(int j = 1; j <= tot && i * prime[j] <= N; j++) { vis[i * prime[j]] = 1; if(!(i % prime[j])) {phi[i * prime[j]] = phi[i] * prime[j]; break;} else phi[i * prime[j]] = phi[i] * (prime[j] - 1); } } while(cin >> N) cout << phi[N] << endl; } int main() { GetPhi(100); return 0; }

例题

因为我太蒻了,所以没有分析,以后在来填咕咕咕。

代码如下:

Copy
#include<bits/stdc++.h> #define int long long using namespace std; int a,m,b; inline int read(int m)//m是要模的数字,读入 { int x=0,f=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch))//只要输入的是阿拉伯数字 { x=x*10+ch-'0';//计算累加 if(x>=m) f=1;//f计算是否超过模数 x%=m;//取模不然会炸 ch=getchar();//继续读入 } return x+(f==1?m:0);//最后看是否超过m如超过就加一个m防止后面计算出误 } inline int ksm(int a,int b)//快速幂函数 { int ans=1; while(b!=0) { if(b%2==1) ans=ans*a%m; a=a*a%m; b=b>>1; } return ans; } inline int phi(int n)//计算有多少个与n互质的数字 { int ans=n,o=sqrt(n);//o为根号n for(int i=2;i<=o;i++)//从2开始枚举到o if(n%i==0) { ans=ans/i*(i-1); while(n%i==0)n/=i; } if(n>1)ans=ans/n*(n-1); return ans; } signed main() { cin>>a>>m; b=read(phi(m));//输入b cout<<ksm(a,b)<<endl;//计算 return 0; }//by wwwaax
posted @   北烛青澜  阅读(67)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
目录