扩展欧几里得与逆元
2017-08-04 18:50
169 查看
第一次去清北学堂就学了扩欧,当时听得很懵,时隔将近两个月又把课件翻出来琢磨,终于明白了,做一下笔记,写的一塌糊涂不一定都对。
补一下欧几里得算法的代码:
欧几里得算法的最终状态就是a=gcd(a,b),b=0。有没有恍然大悟?我们只要令x=1,y=0,显然ax+by=gcd(a,b)。那么问题来了,如何从这一个状态往前推出前一个状态呢?
网上有很多推到给出了公式,但我喜欢颓废 我觉得自己感受过程比死板的公式更易理解。我觉得zhw老师举的这个栗子很好的帮我理解了这个问题。
举栗子之前,首先明确一个众所周知的事实:a%b=a-a/b*b
我们来看栗子:
比如12和7,用朴素欧几里得的过程是这样的:
gcd(12,7)=gcd(7,5)=gcd(5,2)=gcd(2,1)=gcd(1,0)=1。
如果我们倒着推:
末状态:1*1+0*0=1
即1*1+0*(2-2*1)=1 -> 0*2+1*1=1
即0*2+1*(5-2*2)=1 -> 1*5-2*2=1
即1*5-2*(7-1*5)=1 -> -2*7+3*5=1
即-2*7+3*(12-1*7)=1 -> 3*12-5*7=1
求得x=3 y=-5
意不意外?激不激动?如果把当前状态设为x1,y1,a,b,后一个状态设为x2,y2,那么前一个状态可以由后一个状态推导得来:x1=y2,y1=x2-a/b*y2。
这样就可以皆大欢喜地改进欧几里得算法了!
定理:a存在模p的乘法逆元的充要条件是gcd(a,p) = 1。
反证法还是比较好想的,假设gcd(a,p)!=1,那么a*b一定也含有gcd(a,p),就不可能等于1了。
所以我们可以用扩欧求出一组x,y,满足ax+by=1。
可是怎么用扩欧求逆元?看起来多了一项啊。
模掉!(真暴力)
ax+by=1在模b意义下“by”这一项不就没了嘛!
这样,x就可以看做是a模b意义下的乘法逆元。
就可以用扩欧了!
ps:
在p是质数的情况下求逆元还可以用费马小定理!
费马小定理为: a^(p-1)=1 (mod p) (p为质数)
所以,a的逆元就是a^(p-2) mod p,快速幂即可求出。
扩展欧几里得算法
众所周知 老师告诉我们,一定存在整数对(x,y)使得ax+by=gcd(a,b)。扩欧就是来求x和y。怎么求呢?既然叫做【扩展】欧几里得,那肯定是跟欧几里得算法有联系了,只不过在原有算法上“稍加修改”…补一下欧几里得算法的代码:
int gcd(int a,int b) { if(b==0) return a; else return gcd(b,a%b); }
欧几里得算法的最终状态就是a=gcd(a,b),b=0。有没有恍然大悟?我们只要令x=1,y=0,显然ax+by=gcd(a,b)。那么问题来了,如何从这一个状态往前推出前一个状态呢?
网上有很多推到给出了公式,但我喜欢颓废 我觉得自己感受过程比死板的公式更易理解。我觉得zhw老师举的这个栗子很好的帮我理解了这个问题。
举栗子之前,首先明确一个众所周知的事实:a%b=a-a/b*b
我们来看栗子:
比如12和7,用朴素欧几里得的过程是这样的:
gcd(12,7)=gcd(7,5)=gcd(5,2)=gcd(2,1)=gcd(1,0)=1。
如果我们倒着推:
末状态:1*1+0*0=1
即1*1+0*(2-2*1)=1 -> 0*2+1*1=1
即0*2+1*(5-2*2)=1 -> 1*5-2*2=1
即1*5-2*(7-1*5)=1 -> -2*7+3*5=1
即-2*7+3*(12-1*7)=1 -> 3*12-5*7=1
求得x=3 y=-5
意不意外?激不激动?如果把当前状态设为x1,y1,a,b,后一个状态设为x2,y2,那么前一个状态可以由后一个状态推导得来:x1=y2,y1=x2-a/b*y2。
这样就可以皆大欢喜地改进欧几里得算法了!
int exgcd(int a,int b,int &x,int &y) //直接取x,y的地址,直接修改 { if(b==0) { x=1;y=0; return a; } int ans=exgcd(b,a%b,x,y); //ans存储gcd int tmp=x; x=y; y=tmp-a/b*y; return ans; }
逆元
如果a*b=1 (mod p),我们就称b是a模p意义下的乘法逆元。定理:a存在模p的乘法逆元的充要条件是gcd(a,p) = 1。
反证法还是比较好想的,假设gcd(a,p)!=1,那么a*b一定也含有gcd(a,p),就不可能等于1了。
所以我们可以用扩欧求出一组x,y,满足ax+by=1。
可是怎么用扩欧求逆元?看起来多了一项啊。
模掉!(真暴力)
ax+by=1在模b意义下“by”这一项不就没了嘛!
这样,x就可以看做是a模b意义下的乘法逆元。
就可以用扩欧了!
int inver(int a,int p) { int x,y; int gcd=exgcd(a,p,x,y); if(gcd!=1) return -1; //若a,p不互质则无解 int ans=(x%p+p)%p; //x可能是负的 return ans; }
ps:
在p是质数的情况下求逆元还可以用费马小定理!
费马小定理为: a^(p-1)=1 (mod p) (p为质数)
所以,a的逆元就是a^(p-2) mod p,快速幂即可求出。
相关文章推荐
- 数论-hdu-1576-A/B-逆元-扩展欧几里得
- 【数学/扩展欧几里得/线性求逆元】[Sdoi2008]沙拉公主的困惑
- [置顶] 浅析逆元、扩展欧几里得、类欧几里得和莫比乌斯反演(填坑ing)
- HDU1576 A/B (扩展欧几里得求逆元)
- zoj 3609 Modular Inverse 求最小逆元 裸的的扩展欧几里得
- 扩展欧几里得 求解不定方程和逆元
- 扩展欧几里得+逆元
- gcd模板(欧几里得与扩展欧几里得、拓展欧几里得求逆元)
- 组合数,快速幂,扩展欧几里得及其求逆元模板
- 扩展欧几里得求逆元
- HDU 1576 A/B (逆元求扩展欧几里得)
- UESTC 1712 Easy Problem With Numbers 线段树+扩展欧几里得求逆元
- nyoj-Color the necklace(Ploya定理 + 欧拉函数 + 扩展欧几里得(求逆元))
- 【科技】扩展欧几里得 + 逆元
- 扩展欧几里得求逆元:
- hdu5651 xiaoxin juju needs help(扩展欧几里得求逆元)
- Romantic(扩展欧几里得求逆元(裸题))
- hdu1576 A/B 扩展欧几里得求逆元
- 除法取模逆元,扩展欧几里得,费马小定理[数学]
- 【HDU 3037】大数组合取模之Lucas定理+扩展欧几里得求逆元与不定方程一类问题