【学习笔记】欧拉函数 欧拉定理 扩展欧拉定理
欧拉函数 欧拉定理 学习笔记
之前没怎么搞过数论,现在来学学 从最简单的搞起QwQ
欧拉函数
先说几个简单的概念
互质大家应该都懂,就不说了(除了1以外没有其他公因子)
剩余类、完全剩余系、缩系就不说了,不是什么高级的东西,感兴趣可以问我
在数论,对正整数n,欧拉函数
是小于n的正整数中与n互质的数的数目
欧拉函数的推导
公式最后再说,先推一下,需要大力分讨
(1) ,则 ,1与任何数都互质
(2) 是质数,
(3) 是质数的某次方, (p为质数, )
因为从
柿子亦可化简为
(4) 可分解为两互质整数之积, ,
证明需用CRT,有点麻烦,记住就行了(其实就是积性函数)
(5)任意正整数都可以写成质数之积, …
根据(4)可得
再根据(3)可得
即
最终得
综上所述:
这样我们就得到了欧拉函数的通项公式,考虑如何求解
欧拉函数就用欧拉筛(bushi
线性筛素数
保证每个数被最小质因子筛去,通过break做到
void oula()
{
memset(vis,false,sizeof(vis));
for(int i=2;i<=n;i++)
{
if(!vis[i]) prime[++cnt]=i;
for(int j=1;j<=cnt && i<=n/prime[j];j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0) break;
}
}
}
线性筛欧拉函数
用到的三个性质 设
为质数,- 当
为 的一个质因子, - 当
与 互质,
void oula()
{
memset(vis,false,sizeof(vis));
phi[1]=1,cnt=0;
for(int i=2;i<=n;i++)
{
if(!vis[i]) prime[++cnt]=i,phi[i]=i-1; //性质1
for(int j=1;j<=cnt && i<=n/prime[j];j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j]; //性质2
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1); //性质3
}
}
}
求某个数的欧拉函数值
int oula(int x)
{
int res=x;
for(int i=2;i*i<=x;i++)
{
if(x%i==0) res=res/i*(i-1);
while(x%i==0) x/=i;
}
if(x>1)return res=res/x*(x-1);
else return res;
}
欧拉函数性质
-
欧拉函数是积性函数(特别的
) -
的所有因子的欧拉函数值之和为 -
还有一部分就是上面证明中提到的了qwq
欧拉定理
欧拉定理的证明
首先举出几个引理
引理一
- 若
三个任意整数与正整数 ,满足 与 互质,则如果 ,那么 - 证明:由同余的同加性可知,
,即 , ,因此 不为 的倍数,即 为 的倍数, ,
引理二
属于 的缩系,则 也属于 的缩系- 证明:若
与 互质,则 也与 互质(因为 中都没有与 相同的因子,所以 也没有与 相同的因子),因此(可由反证法得知) 也与 互质
引理三
互质,且 ={ , ,…, }为 的完全剩余系,则 ={ , ,…, }也构成 的完全剩余系- 证明:假设
,由引理一可知 ,因为是其都属于 的完全剩余系,所以 ,产生了矛盾,因此 ,在 中两两之间都满足这一性质,即满足其为 的完全剩余系
引理四
互质,且 ={ , ,…, }为 的简化剩余系(缩系),则 ={ , ,…, }也为其简化剩余系- 证明:首先由引理三推出一个完全剩余系,然后根据引理二可证明此引理
证明欧拉定理
则
即
后者(
欧拉定理的一点小扩展
证明
设
因为
扩展欧拉定理
由上得
则
证明扩展欧拉定理
取
欧拉定理得
设
即
因此可得
即
然后质因子分解
综上所述:扩展欧拉定理成立
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define int long long
using namespace std;
int phi,a,m,b,flag;
int ksm(int a,int b)
{
int ans=1;
for(;b;b>>=1,a=(a*a)%m)
{
if(b&1) ans=(ans*a)%m;
}
return ans;
}
int oula(int x)
{
int res=x;
for(int i=2;i*i<=x;i++)
{
if(x%i==0) res=res/i*(i-1);
while(x%i==0) x/=i;
}
if(x>1)return res=res/x*(x-1);
else return res;
}
signed main()
{
scanf("%d%d",&a,&m);
int mid=m; phi=oula(m); char ch;
while ((ch=getchar())<'0' || ch>'9');
while (b=b*10ll+(ch^48),(ch=getchar())>='0' && ch<='9')
{
if (b>=phi) flag=1,b%=phi;
}
if(b>=phi) b%=phi,flag=true;
if(flag) b+=phi;
printf("%lld",ksm(a,b));
return 0;
}
例题
上帝与集合的正确用法
差不多是个裸题,柿子都给出来了,直接递归就好,然后用扩展欧拉定理求解即可
AC code
点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define int long long
using namespace std;
const int maxn=1e7+5;
inline int read()
{
int w=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9')
{
w=(w<<3)+(w<<1)+(ch^48);
ch=getchar();
}
return w*f;
}
int t,p,cnt;
int phi[maxn];
bool vis[maxn];
int prime[maxn];
int ksm(int a,int b,int mod)
{
int ans=1;
for(;b;b>>=1,a=(a*a)%mod)
{
if(b&1) ans=(ans*a)%mod;
}
return ans%mod;
}
void oula()
{
phi[1]=1,cnt=0;int n=maxn-5;
for(int i=2;i<=n;i++)
{
if(!vis[i]) phi[i]=i-1,prime[++cnt]=i;
for(int j=1;i<=n/prime[j] && j<=cnt;j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
int solve(int x)
{
if(x==1) return 0;
return ksm(2,solve(phi[x])+phi[x],x);
}
void work()
{
printf("%lld\n",solve(read()));
}
signed main()
{
oula();t=read();while(t--) work();
return 0;
}
总结
其实就三句有用的
- 欧拉公式
- 欧拉定理
, - 扩展欧拉定理
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误