扩展欧几里德与乘法逆元

扩展欧几里得:

扩展欧几里得是在欧几里得的基础上扩充而来:

 

gcd(a, b) = gcd(b, a mod b)

对于不全为 0 的非负整数 a、b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。

 

 

 

就是给两个整数 a,b 必然存在一对整数 x,y 使得 ax + by = gcd(a,b),这个定理又叫贝祖定理。

证明:

假如 a > b, 且 b = 0,那么很明显, ax + by = ax + 0 = gcd(0, a mod 0) = a,也就是 x = 1。扩展欧几里德算法是成立的。

若a≠0 && b≠0,那么

设a*x1+b*y1 = gcd(a,b); 

那么 gcd(b,a mod b) = b*x2 + (a mod b) *y2;

因为gcd(a,b) = gcd(b,a mod b); 则 a * x1 + b * y1 = b * x2 + (a mod b) * y2;

然后化简:a % b = a - (int)(a/b) * b;

a * x1 + b * y1 = b * x2 + (a - (int)(a/b) * b) * y2
 

    a * x1 + b * y1 = b * x2 + a * y2 - (int)(a/b) * b * y2

    合并同类项

    a * x1 + b * y1 = a * y2 + b ( x2 - (int)(a/b) * y2 )

 得到结论:    x1 = y2

                      y1 = x2 - (int)(a/b) * y2。

 

 

int ex_gcd(int a,int b,int &x,int &y){
	if(b == 0){
		x = 1;
		y = 0;
		return a;
	}
	int ans = ex_gcd(b,a%b,x,y);
	int temp = x;
	x = y;                     //x1=y2;
	y = temp - a/b*y;          //y1 = x2-a/b*y2;
	return ans;
}

 

 

 

 

 

 

 

乘法逆元:(在维基百科中也叫倒数,当然是 mod p后的)

a ≡1mod(f) ;

 

就相当于求 a*x+f*y=1 , gcd(a,f) == 1时有解(a,f互素)。

 

 

 

例如:

4关于1模7的乘法逆元为多少?

4X≡1 mod 7

这个方程等价于求一个X和K,满足

4X=7K+1

其中X和K都是整数。

若ax≡1 mod f, 则称a关于模f的乘法逆元为x。也可表示为ax≡1(mod f)。

a与f互素(1=gcd())时,a关于模f的乘法逆元有解。(a*x+b*y=c,  c=gcd(a,b)是方程有解的充要条件)如果不互素,则无解。如果f为素数,则从1到f-1的任意数都与f互素,即在1到f-1之间都恰好有一个关于模f的乘法逆元。

int cal(int a,int m){
    int x,y;
    int gcd = ex_gcd(a,m,x,y);
    if( (1%gcd)!=0 ) return -1;
    x*=1/gcd;
    int ans = x%abs(m);
    if(ans<=0) ans+=m;
    return ans;
}

做题时如果结果过大一般都会让你模一个数,确保结果不是很大,而这个数一般是1e9+7,而且这个数又是个素数,加减乘与模运算的顺序交换不会影响结果,但是除法不行。有的题目要求结果mod一个大质数,如果原本的结果中有除法,比如除以a,那就可以乘以a的逆元替代。(除一个数等于乘它的倒数,虽然这里的逆元不完全是倒数,但可以这么理解,毕竟乘法逆元就是倒数的扩展)。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

void exgcd(ll a,ll b,ll& d,ll& x,ll& y)
{
    if(!b) { d = a; x = 1; y = 0; }
    else{ exgcd(b, a%b, d, y, x); y -= x*(a/b); }
}

ll inv(ll a, ll p)
{
    ll d, x, y;
    exgcd(a, p, d, x, y);
    return d == 1 ? (x+p)%p : -1;
}

int main()
{
    ll a,p;
    while(1)
    {
        scanf("%lld %lld",&a,&p);
        printf("%lld\n",inv(a,p));
    }
}

 

逆元线性筛:

const int mod = 1000000009;
const int maxn = 10005;
int inv[maxn];
inv[1] = 1;
for(int i = 2; i < 10000; i++)
    inv[i] = inv[mod % i] * (mod - mod / i) % mod;

阶乘的逆元:


inv[maxn]=mod_pow(fac[maxn],mod-2);
for(ll i=maxn-1;i>=0;i--)
    inv[i]=(inv[i+1]*(i+1))%mod;


3.费马小定理。

假如a是一个整数,p是一个质数,那么   a的p次方-a   是p的倍数,可以表示为




如果a不是p的倍数,这个定理也可以写成




由费马小定理 ap-1≡1 , 变形得 a*ap-2≡1(mod p),:若a,p互质,因为a*ap-2≡1(mod p)且a*x≡1(mod p),则x=ap-2(mod p),用快速幂可快速求之。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值