欧拉定理及其推论,裴蜀定理,计算欧拉函数
欧拉定理#
内容:若正整数
证明:设
首先我们来考虑一些数:
这些数有如下两个性质:
(1)任意两个数模
证明:若存在
那么因为有
(2)
对于任意的
把上面两个性质结合一下来说,
因此我们可以写出以下式子:
即:
又因为
裴蜀定理#
定义:若
简单来说,我们设
首先来证明一下
先不要去想那个式子,先来想一想怎么求
用辗转相除法对
我们设
设
重复此过程可以得到下面的式子:
因为辗转相除法最后得到的余数为
移项一下,得:
将(1)移项得:
将(4)带入(3)式得到:
把式子展开后,可以表示成
合并一下同类项,得:
这系数有点长,换个字母代替一下:
简洁多了,上面所有的字母代表的都是整数,所以
如果把(3)表示成
当我们将这两个式子一直像上面的做法一样一直搞下去,就可以得到(学长说就是一个不断递归的过程,自己手模一下可能会好理解一些):
显然
于是就有一个很重要的推论:
对于方程
有了上面的证明,这个就很容易证(本来不打算写证明了但万一有人看呢)。
证明:
设
两边同时除以
显然,如果此时
故只有当整数
然后,判断二元不定方程是否有整数解的方法出现了:
对于方程
证明(吐了):
设
对于方程
两边同时乘上
因为
所以方程
然后这东西还可以扩展到
对于不定方程
对于不定方程
所有系数
终于结束了(上面的证明自己推一下就好啦)。
欧拉定理推论#
若正整数
证明(跟费马小定理差不多好像):
把上面那个式子变一下形:
这个推论可以帮助我们在求幂运算的时候缩小数据范围和计算次数。具体的说:在求乘方运算时,可以先把底数对
特别的,如果
计算欧拉函数#
来说一下如何计算欧拉函数的值,因为做模板题被 T 痛了。
参考:自为风月马前卒
第一种方法就是直接暴力循环枚举小于等于
第二种方法:大约是
当
当
当
这个最难搞,先对
设
假设
辣么
证明:
与一个数互素的数的个数就是这个数减去与他不互素的数的个数,因为
当
好的把 dalao 的代码放在下面:
#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:若
性质2:若
则
这一步同时利用了性质1和欧拉函数的积性。
性质3:若
则
证明就算了吧咕咕咕。
dalao 代码:
#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;
}
因为我太蒻了,所以没有分析,以后在来填咕咕咕。
代码如下:
#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
作者: 北烛青澜
出处:https://www.cnblogs.com/Multitree/p/16744312.html
本站使用「CC BY 4.0」创作共享协议,转载请在文章明显位置注明作者及出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!