求逆元
求 7 关于 26 的逆元!
扩展的欧几里得算法
#include#include //欧几里得函数 void exgcd(int a, int b, int &x, int &y, int &d) { if (!b) { d = a, x = 1, y = 0; } else { exgcd(b, a % b, y, x, d); y -= x * (a / b); } } int inv(int t, int p) { //返回t对p的逆元 int d, x, y; exgcd(t, p, x, y, d); return (x % p + p) % p; //x可能为负,也可能过大 } int main() { int m = 7, n = 26; printf("%d", inv(m, n)); return 0 ; }
或者
#include#include int exgcd(int a,int b,int &x,int &y)//扩展欧几里得算法 { if(b==0) { x=1,y=0; return a; } int ret=exgcd(b,a%b,y,x); y-=a/b*x; return ret; } int getInv(int a,int mod)//求a在mod下的逆元,不存在逆元返回-1 { int x,y; int d=exgcd(a,mod,x,y); return d==1?(x%mod+mod)%mod:-1; } int main() { int m = 7, n = 26; printf("%d", getInv(m, n)); return 0 ; }
手算
方法1(辗转相除法)
求7关于26的逆元,即 7 -1
设 7-1 为 X,即7 * X = 1 mod 26 ,求 X 即可
26 / 7 = 3 余 5
7 / 5 = 1 余 2
5 / 2 = 2 余 1
则:
1 = 5 - 2 * 2
1 = 5 - 2 * (7 - 5 * 1) = 3 * 5 - 2 * 7
1 = 3 * (26 - 3 * 7) - 2 * 7= 3 * 26 - 11 * 7
故 7-1 = -11,由于 -11 不在Zq*中,故 7-1 = 26 - 11 = 15
方法2
参考:链接
原理:
首先对余数进行辗转相除:
N = A * a0 + r0
A = r0 * a1 + r1
r0 = r1 * a2 + r2
r1 = r2 * a3 + r3
…
rn-2 = rn-1 * an + rn
rn-1 = rn * an+1 + 0对上面的商数逆向排列(不含余数为0的商数):
其中:
b-1 = 1
b0 = an
bi = an-1 * bi-1 + bi-2
商个数为偶数,则bn即为所求的逆元B;
商个数为奇数,则N-bn即为所求的逆元B
求7关于26的逆元:
辗转相除法:
26 = 3 * 7 + 5
7 = 1 * 5 + 2
5 = 2 * 2 + 1
因为商的个数为奇数,故 7-1 = 26 - 11 = 15
方法3(Bezout恒等式)
原理:用矩阵行初等变换的方法求Bezout,进而求逆元
参考:链接
求多项式的乘法逆元
原理:用矩阵行初等变换的方法求Bezout,进而求逆元
Bezout恒等式
设a , b ∈ Z ,则a , b的最大公约数可以表示为:
g c d ( a , b ) = d = s a + t b
把d = s a + t b称作Bezout恒等式。
更多Bezout恒等式请参考:链接
矩阵的行初等变换求解Bezout恒等式
这里以一个具体的实例来说明,求g c d ( 5 , 177 ):
1、先把欲求的两个数写成如下的矩阵形式,即是以5和17为第一列,后面拼一个单位矩阵。
2、将上述矩阵行初等变换至5和17这两个位置任意一个为0即可,另一个位置的值就是a和b的最大公约数。
3、得到Bezout恒等式,上述两个*位置表示这个问题中,不需要关注那两个位置的值
1 = 177 ? ? 2 + 71 ? 5
4、如果最大公约数为1,则可以方便的看出其中一个元素的逆元。上式两端同时模177
71 ? 5 ≡ 1 m o d 177
5、这样就得到71和5在Z 177 中 的 逆 元,即5相对于177的逆元是71
求解G F ( 2 8)上的多项式乘法逆元
求通过不可约多项式x 8 + x 4 + x 3 + x + 1构造G F ( 2 8 )上( 09 ) H?在上的乘法逆元。
1.( 09 )H?转换为多项式
( 09 ) H = 00001001 = x 3 + 1
2.求x 3 + 1在x 8
+ x 4 + x 3 + x + 1上的逆元,构造矩阵
3.行初等变换至标准形式(注意合并多项式的时候系数是模2加法)
4.具体的变换步骤,这里就不详细展开,但给出变换的顺序
- r 1 ? x 5 r 2
- r 1 ? x 2 r 2
- r 1 ? x r 2
- r 1 ? r 2
- r 2 ? x r 1
- r 1 ? x 2 r 2
5.最后得到:
即:1 = x.m(x) + (x6 + x3 + x2 + x + 1).( x3 + 1)
6.显然x 3 + 1的逆元为x 6 + x 3 + x 2 + x + 1 ,转换为2进制表示01001111,16进制表示( 4 F ) H
大数求逆元
使用miracl库
int main()
{
/*求m的逆元n,即m.n=1 mod p*/
printf("求m的逆元n,即m.n=1 mod p\n\n");
miracl* mip = mirsys(MAX_D + 10, 10);
big p = mirvar(0);
big m = mirvar(0);
big n = mirvar(0);
big one = mirvar(0);
char one_0[2] = { "1" };
cinstr(one, one_0);
printf("请输入(m,p):\n");
cinnum(m, stdin);
cinnum(p, stdin);
xgcd(m, p, n, n, one);
printf("\n输出n:");
cotnum(n, stdout);
mirexit();
system("pause");
return 0;
}