逆元与(扩展)欧拉定理

本文主要讲了逆元、(扩展)欧拉定理。

快速模幂

P1226 【模板】快速幂||取余运算

假设p为奇数,则bp=b2p2+1=(b2)p2×b,否则bp=b2p2=(b2)p2

这样可以写一个循环来实现,在p=0时结束循环即可。

#include <bits/stdc++.h>
using namespace std;
int a,b,c,x,y,p,m=1;
int main() {
    for(scanf("%d%d%d",&a,&b,&p),x=a,y=b; b; b>>=1) {
        if(b&1)m=(m*1ll*a)%p;//b为奇数
        a=(a*1ll*a)%p;//将a平方
    }
    printf("%d^%d mod %d=%d\n",x,y,p,m);
    return 0;
}

乘法逆元

对于关于x的同余方程ax1(modp),当且仅当gcd(a,p)=1时有解,有解时最小正整数解即为a在模p意义下的逆元,记号为a1

例如3在模10意义下的逆元即为7

线性筛逆元

P3811 【模板】乘法逆元

首先1在模p意义下的逆元必定为1

我们考虑n2p意义下的逆元。

q=pn,r=p%n,则p=nq+r(带余除法的性质)

nq+r0(modp)

nq移项到右边,两边同时乘上n1r1

n1q×r1(modp)

q=pn,r=p%n代入

n1(pn)(p%n)1(modp)

n1(ppn)(p%n)1(modp)

代码:

#include <bits/stdc++.h>
using namespace std;
int mod,n,inv[20000528];
int main() {
    scanf("%d%d",&n,&mod),inv[1]=1,printf("1\n");
    for(int i=2; i<=n; ++i) {
        inv[i]=(mod-mod/i)*1ll*inv[mod%i]%mod;
        printf("%d\n",inv[i]);
    }
    return 0;
}

欧拉定理

gcd(a,p)=1,则aφ(p)1(modp)

证明:(可不看)

剩余类

剩余类,亦称同余类。

我们把(所有)对模n同余的整数构成的一个集合叫做模n的一个剩余类。

qn+rq,r为任意整数)所表示的所有数就是与rn同余的剩余类

例如,11,5,1,7,13,就是与16同余的剩余类

简化剩余系

简化剩余系也称既约剩余系或缩系

在与 与n互素的整数 模n同余的所有剩余类中,从每一个类中各任取一个数作为代表组成的集合,叫做模n的一个简化剩余系。

例如模5的一个简化剩余系是1,2,3,4,模30的一个简化剩余系是1,7,11,13,17,19,23,29

根据φ(n)的定义,模n的简化剩余系有φ(n)个元素。

根据简化同余系的定义,每个模n的简化剩余系的所有元素的乘积模n相等。

证明

x1,x2,,xphi(p)是一个以p为模的缩系。

而且gcd(a,p)=1,则gcd(axi,p)=1

所以ax1,ax2,,axphi(p)也是一个以p为模的缩系。

所以i=1φ(p)axii=1φ(p)xi(modp)

所以aφ(p)1(modp)

费马小定理

p为质数时,apa(modp)

证明:

a,p不互质时即p|a,显然成立

a,p互质时,根据欧拉定理得aφ(p)1(modp)

而且p为质数时,φ(p)=p1,代入上式后两边同时乘a即可得证。

变式

gcd(a,p)=1时,a×aφ(p)11(modp)

ap意义下的逆元为aφ(p)1(当p为质数时,a的逆元为ap2)

快速幂求逆元

直接用欧拉定理的式子即可

#include<bits/stdc++.h>
using namespace std;
int getphi(int n) {
	int tmp=n,ans=n;
	for(int i=2; i*i<=tmp; ++i)
		if(!(tmp%i)) {
			ans-=ans/i;
			while(!(tmp%i))tmp/=i;
		}
	return tmp>1?ans-ans/tmp:ans;
}
int a,b,p,m=1;
int main() {
	for(scanf("%d%d",&a,&p),b=getphi(p)-1; b; b>>=1) {
		if(b&1)m=(m*1ll*a)%p;
		a=(a*1ll*a)%p;
	}
	printf("%d\n",m);
	return 0;
}

扩展欧几里得求逆元

扩展欧几里得相关见同余基础数论详解

P1082 [NOIP2012 提高组] 同余方程

这题其实就是求ab意义下的逆元。

有解说明gcd(a,b)|1,那么gcd(a,b)=1,直接用扩展欧几里得解同余方程即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,mod,x,y,d;
void exgcd(ll a,ll b,ll&x,ll&y,ll&gcd) {
	if (!b) gcd=a,x=1,y=0;
	else exgcd(b,a%b,y,x,gcd),y-=a/b*x;
}
int main() {
	scanf("%lld%lld",&a,&mod);
	exgcd(a,mod,x,y,d);
	printf("%lld\n",(x%mod+mod)%mod);//记得取模
	return 0;
}

求多个数的逆元

P5431 【模板】乘法逆元2

我们这题要求a1,a2,,anp意义下的逆元,我们可以试着用O(n+logp)

si=i=1iaimodp,可以O(n)预处理出si

再设bi+1=i=1i(ai)1(modp),可得(ai)1bi+1×si1(modp)

接下来就是要考虑如何处理bi+1

预处理si后,bn+1=sn1(modp),是O(logp)

之后in1的循环,算出ai1bi+1×si1(modp),同时算出bibi+1×ai(modp)即可。

总复杂度O(n+logp)

#include <bits/stdc++.h>
using namespace std;
inline int read() {
    int x=0,c=getchar();
    for(; c<=47||c>=58; c=getchar());
    for(; c>=48&&c<=57; c=getchar())x=(x<<3)+(x<<1)+(c&15);
    return x;
}
const int MAXN=1<<23;
int n,mod,k,b[MAXN],s[MAXN],a[MAXN],inv[MAXN],ans;
int fastpow(int a,int k) {
    int base=1;
    for(; k; a=((0ll+a)*a)%mod,k>>=1)
        if(k&1)
            base=((0ll+base)*a)%mod;
    return base;
}
int main() {
    s[0]=1;
    n=read(),mod=read(),k=read();
    for(int i=1; i<=n; ++i) {
        a[i]=read();
        s[i]=s[i-1]*1ll*a[i]%mod;//预处理si
    }
    b[n+1]=fastpow(s[n],mod-2);
    for(int i=n; i>=1; --i) {
        inv[i]=b[i+1]*1ll*s[i-1]%mod;//逆元
        b[i]=b[i+1]*1ll*a[i]%mod;//bi
    }
    int tmp=k;
    for(int i=1; i<=n; i++) {
        ans=(ans+inv[i]*1ll*tmp)%mod;//计算答案
        tmp=(tmp*1ll*k)%mod;
    }
    printf("%d\n",ans);
    return 0;
}

有理数取余

P2613 【模板】有理数取余

aba×b1(modp)

直接用上面说的求逆元即可。

#include<bits/stdc++.h>
using namespace std;
const int mod=19260817;
inline int read() {
	int x=0,c=getchar();
	for(; c<=47||c>=58; c=getchar());
	for(; c>=48&&c<=57; c=getchar())x=((x<<3)+(x<<1)+(c&15))%mod;
	return x;
}
int fastpow(int a,int k) {
	int base=1;
	while(k) {
		if(k&1) base=base*1ll*a%mod;
		a=a*1ll*a%mod;
		k>>=1;
	}
	return base;
}
int a,b;
int main() {
	a=read(),b=read();
	printf("%d\n",a*1ll*fastpow(b,mod-2)%mod);
	return 0;
} 

扩展欧拉定理

bφ(m)时,aba(bmodφ(m))+φ(m)(modm)

P5091 【模板】扩展欧拉定理

证明:

首先m=1时,φ(m)=1,结论成立。

任取一个质数pm就可以写成pr×s,其中r0,gcd(p,s)=1

φ(pr)×φ(s)=φ(m)φ是积性函数)

由欧拉定理得pφ(s)1(mods),则pφ(m)1(mods)

可以设pφ(m)=ts+1,将式子两边乘上pr

pφ(m)+r=tm+pr,即pφ(m)+rpr(modm)

br时,pbpbrprpbrpφ(m)+rpb+φ(m)(modm)

rφ(pr)φ(m),所以在bφ(m)时,上式成立。

改写一下上面的结论:

b2φ(m)bφ(m)φ(m)时,pbpbφ(m)(modm)

也就是pbp(bmodφ(m))+φ(m)(modm)

a分解质因数后得到的所有质数都会满足上式,把它们乘起来就是a也满足。

模板题代码:

#include <bits/stdc++.h>
using namespace std;
int m,a,b,phi;
int getphi(int n) {//求phi
	int tmp=n,ans=n;
	for(int i=2; i*i<=tmp; ++i)
		if(!(tmp%i)) {
			ans-=ans/i;
			while(!(tmp%i))tmp/=i;
		}
	return tmp>1?ans-ans/tmp:ans;
}
void read(int&b) {
	bool gt=0;
	char c=getchar();
	for(; c<'0'||c>'9'; c=getchar());
	for(; c>='0'&&c<='9'; c=getchar()) {
		b=(b<<3)+(b<<1)+(c^48);
		gt|=b>=phi;//判断b是否大于phi
		b%=phi;
	}
	if(gt)b+=phi;//不大于就不能加
}
int quickpow(int a,int b,int p) {//快速幂
	int m=1;
	while(b) {
		if(b&1)m=(m*1ll*a)%p;
		a=(a*1ll*a)%p;
		b>>=1;
	}
	return m;
}
int main() {
	scanf("%d%d",&a,&m),phi=getphi(m),read(b);
	printf("%d\n",quickpow(a,b,m));
	return 0;
}

一道题

P4139 上帝与集合的正确用法

这个222明显大于φ(p),根据扩展欧拉定理

2222222modφ(p)+φ(p)(modp)

这样就可以递归,直到p=1,2时返回0即可。

#include<bits/stdc++.h>
using namespace std;
int fastpow(int a,int k,const int mod) {
	int base=1;
	while(k) {
		if(k&1)base=base*1ll*a%mod;
		a=a*1ll*a%mod;
		k>>=1;
	}
	return base;
}
int phi(int n) {
	int tmp=n;
	for(int i=2; i*i<=n; ++i)
		if(!(n%i))
			for(tmp-=tmp/i; !(n%i); n/=i);
	return n>1?tmp-tmp/n:tmp;
}
int solve(int mod) {
	int t=phi(mod);
	return mod==1||mod==2?0:fastpow(2,solve(t)+t,mod);//递归
}
int n,t;
int main() {
	scanf("%d",&t);
	while(t--) {
		scanf("%d",&n);
		printf("%d\n",solve(n));
	}
	return 0;
}
posted @   mod998244353  阅读(499)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
Live2D
欢迎阅读『逆元与(扩展)欧拉定理』
点击右上角即可分享
微信分享提示