数论:gcd_ax+by=k求解_逆元

目录

1.常见结论

2.最大公约数 最小公倍数 

3. 扩展欧几里得

  1)判断方程ax+by=k是否有解:k | gcd ( a,b )

  2)求ax+by=k的任意一组解、通解、最小整数数

  3)求逆元

3. 逆元  

  1)费马小定理

  2)线性算法 

  3)扩展欧几里得 

  4)递推求阶乘逆元

相关习题 


1.常见结论

   

2.最大公约数 最小公倍数 

gcd:除数/余数 (欧几里得 辗转相除法)

lcm:ab / gcd( a,b )

inline int gcd(int a,int b){
	int r;
	while(b){
		r=a%b;
		a=b,b=r;
	}return a;
}
inline int lcm(int a,int b){
	return 1ll*a/gcd(a,b)*b;
}

3. 扩展欧几里得

扩展欧几里得算法结论

扩展欧几里得求通解、最小正整数解过程

扩展欧几里得求任意解推导过程

                ax + by = gcd( a,b ) 的解一定存在

  1)判断方程ax+by=k是否有解:k | gcd ( a,b )

  2)求ax+by=k的任意一组解、通解、最小整数数

  1. 任意一组解:x0 = x0 * (k / gcd( a,b ))             y0 = y0 * (k / gcd( a,b ))  
  2. 通解:
    1. x=x0 + b / gcd(a,b) * i  (相当于x每次可以增减:b/gcd的整数倍) 
    2. y=y0 - a / gcd(a,b) * i  (相当于y每次可以减增:a/gcd的整数倍)
  3. 最小整数解:

              x= ( x + b / gcd *i ) % ( b / gcd ) = x%( b / gcd )   (b/gcd(a,b)应取正)                                            若 x <= 0,则 x += b/gcd

  3)求逆元

        若 a 关于 p 的逆元 x 存在,则 gcd ( a , p ) = 1,a x ≡ 1 mod  p 
        我们可以得到 a x + p k = 1 ,其实就是 ax + pk = gcd( a,p )
        所以求出一个最小的 x 就是 a 关于 p 的一个逆元

inline int exgcd(int a,int b,int &x,int &y){
	if(!b){
		x=1,y=0;
		return a;
	}
	int _x,_y;
	int d=exgcd(b,a%b,_x,_y);
	x=_y;
	y=_x-a/b*x;
	return d;
}
int main(){
	int a,b,k,x,y;
	scanf("%d%d%d",&a,&b,&k);
	int d=exgcd(a,b,x,y);
	//1.解是否存在
	bool f=0;
	if(k%d==0) f=1;
	
	//2.求解
		//任意 
		x=x*(k/d); y=y*(k/d);
		//通解 
		x=x+b/d*i; y=y-a/d*i;//i任意 
		//最小整数解
        x=x%(b/d);
		if(x<0)x+=b/d;
	
	//3.求逆元x
	if(d==1)x; 
}

 

3. 逆元  

逆元概念_三种求法 (费马小定理,扩展欧几里得推导,递推求阶乘逆元)

线性算法求逆元

若xy≡1 (mod p),且gcd(x,p)=1(gcd函数是求x,y的最大公约数),则称x关于模p的乘法逆元为y。
那么除以y相当于乘以x(模p情况下)。值得注意的是x
(y+k*p)≡1(mod p),逆元不止一个,求最小的就可以;

  1. 费马小定理:
  2. 扩展欧几里得:a x + b y = gcd ( a , b ) 的解一定存在。ax+pk=1,可求出一个最小的 x 就是 a关于 p 的一个逆元
  3. 递推求阶乘逆元:

  1)费马小定理

        gcd(a,p)=1,那么 a^{p-2} * a ≡ 1mod p,可得求 a 的逆元,就直接用快速幂求 a^{p-2}

inline ll quickp(ll base,ll pow=mod-2){
	ll res=1;
	while(pow){
		if(pow&1)res=res*base%mod;
		pow>>=1;
		base=base*base%mod;
	}return res;
} 
inline ll inv(ll x){
	return quickp(x,mod-2);
}

  2)线性算法 

        设t=p%i , r=p/i ; 则可以得到 i*r+t=p -->i * r+t ≡ 0(mod p)

        式子两边同时乘以i-1 * t-1 (i,t的逆元)得 t-1*r+ i-1≡0(mod p)

        即i-1≡(-r)*t-1(mod p) , 由t=p%i可得t<i,所以 i 的逆元可以由比 i 小的 t 的逆元求出来

        因为逆元是正数,而此时i-1的为负值,所以 i-1≡(-r)*t-1+t-1 * p≡(p-r)*t-1(mod p)(加上t-1倍的p后逆元就是正的了,但是要记得取模)

        那么化简并带入 t=p%i,r=p/i 可得 i-1=(p-p/i)* (p%i)-1%p

typedef long long ll;
ll inv[3000010];
void line(ll n,ll p)
{
    inv[1]=1;
    for(int i=2;i<=n;i++)
    {
        inv[i]=(p-p/i)*inv[p%i]%p;
    }
}

  3)扩展欧几里得 

  4)递推求阶乘逆元

        用费马小定理先求出最大那个阶乘的逆元在递归

        用预处理的阶乘和阶乘逆元计算组合数

int fac[N],ifac[N];//阶乘,阶乘的逆元 初始化1e6的数组大约用200MS。1秒的时限处理不完1e7
inline ll quickp(ll base,ll pow=mod-2){
	ll res=1;
	while(pow){
		if(pow&1)res=res*base%mod;
		pow>>=1;
		base=base*base%mod;
	}return res;
} 

inline void init(){
	fac[0]=ifac[0]=1;
	for(int i=1;i<N;i++)fac[i]=1ll*fac[i-1]*i%mod;
	ifac[N-1]=quickp(fac[N-1]);
	for(int i=N-2;i;i--)ifac[i]=1ll*ifac[i+1]*(i+1)%mod;
}

inline int C(int n,int m)//求组合数{
    if(n<m) return 0;
    return  1ll*fact[n]*ifact[m]%mod*ifact[n-m]%mod;
}

相关习题 

P3811 【模板】乘法逆元 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 费马小定理>扩展欧几里得会超时>线性算法

Problem - 1576 (hdu.edu.cn) 快速幂求逆元

Problem - 2669 (hdu.edu.cn) exgcd求最小整数解

Problem - 5698 (hdu.edu.cn) 递推预处理阶乘逆元+组合数 / 扩展欧几里得+组合数(打表找规律发现杨辉三角)

1061 -- 青蛙的约会 (poj.org) exgcd求最小整数解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值