欧拉定理和辗转相减法求解逆元matlab

目录

欧拉定理求逆

欧拉定理

欧拉函数的通式

欧拉筛

欧拉筛代码

演示结果

EULER_F.m

输出的质数表

防溢出

欧拉定理求逆元的代码

辗转相减法求逆

更相减损术

迭代式:

辗转相减求逆代码

检验结果

小结


上一篇文章讲了求逆的扩欧法和公式法,这一次讲欧拉定理法和辗转相减法。

欧拉定理求逆

欧拉定理

对于 a和模 n,a和n互质, a^φ(n) = 1(mod n)。

φ(n)为欧拉函数,是2 - n-1中,所有和n互质的数加1。其中,φ(1)=φ(2)=1。

这个式子太熟悉了。把其中一个a提出来,就变成了a*a^(φ(n) -1) = 1(mod n),a的逆元就是a^(φ(n) -1)。

欧拉函数的通式

如果n可以被分解成若干个质因数的乘积pm,则

φ(n)=n*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)*……*(1-1/pm)

若n为质数,则φ(n) = n - 1;

(如果n可以被分解成两个质数p,q的乘积,那么欧拉函数就是两个质数的欧拉函数的乘积(p-1)*(q-1)

质因数是指,可以被n整除的质数,或者说是n的因数中不可再分的因数。

所以用欧拉定理求逆的关键在于,判断n有没有质因数。即找到比n小的质数,判断是否可以整除。

寻找比n小的质数,这里使用欧拉筛来筛选素数。

欧拉筛

欧拉筛相比起其他筛素数的方法的特点是,不会重复筛选。所以效率是有保障的。

步骤是这样的:

建立一个合数集和质数。初始都是空集。

从2开始遍历,一直到n。(这里用来筛选所有小于n的质数,如果只是要筛选质因数,到n/2就可以了)

判断是否是质数的条件,就是判断它是否出现在合数集中。没有出现在合数集,就储存在质数集中。

判断是合数的条件,就是用遍历中的每个数,乘以质数集里面的每个数,得到的这些乘积就是合数。

一开始合数集和质数集是空的,先判断质数,然后再乘以质数集的元素储存合数。

如果乘积大于n,用不上,就不储存啦。

为了避免重复储存合数,这里用比较小的质数来储存合数。比如24 = 2*12 = 3*8 = 4*6,这里24可以在遍历到6,8,12的时候都可以储存,为了避免重复储存,应该避免在在6的时候乘到4,和8的时候乘到3。即遍历的数不能乘以比它质因数还大的质数。

代码如下:

欧拉筛代码

isnot_prime = zeros(1 , n);%判断是否是合数
prime = [];%质数集
for i = 2:n
    if (isnot_prime(i) == 0)
        prime(end + 1) = i;
    end
    for j = 1 : length(prime)
        if((i*(prime(j))>n))
            break;
        end
        isnot_prime(i*(prime(j))) = 1;
        if(mod(i , prime(j)) == 0)
            break;
        end
    end
end

演示结果

n = 2  ---not prime:  4  
n = 3  ---not prime:  6    9  
n = 4  ---not prime:  8  
n = 5  ---not prime:  10    15    25  
n = 6  ---not prime:  12  
n = 7  ---not prime:  14    21    35    49  
n = 8  ---not prime:  16  
n = 9  ---not prime:  18    27  
n = 10  ---not prime:  20  
n = 11  ---not prime:  22    33    55    77    121  
n = 12  ---not prime:  24  
n = 13  ---not prime:  26    39    65    91    143    169  
n = 14  ---not prime:  28  
n = 15  ---not prime:  30    45  
n = 16  ---not prime:  32  
n = 17  ---not prime:  34    51    85    119    187    221    289  
n = 18  ---not prime:  36  
n = 19  ---not prime:  38    57    95    133    209    247    323    361  
n = 20  ---not prime:  40  

然后再加上判断质因数的个数,来求欧拉函数就好了。我这里遍历到了n,如果最后的质因数等于它本身,那么它就是质数,欧拉函数就是n-1,如果不是质数,就按照通式计算。

求欧拉函数的代码:

EULER_F.m

%计算欧拉函数claculate the Euler function
function e = EULER_F(n)
isnot_prime = zeros(1 , n);%判断是否是质数
prime = [];%质数集
primen = [];%质因数集
if(n == 1)
    e = 1;
    return;
end
for i = 2:n
    if (isnot_prime(i) == 0)
        prime(end + 1) = i;
    end
    for j = 1 : length(prime)
        if((i*(prime(j))>n))
            break;
        end
        isnot_prime(i*(prime(j))) = 1;
        if(mod(i , prime(j)) == 0)
            break;
        end
    end
end
for k = 1:length(prime)
    if(mod(n , prime(k)) == 0)
        primen(end + 1) = prime(k);
    end
end
if(primen(length(primen)) == n)
    e = n-1;
else
    e = n;
    for i = 1 : length(primen)
        e = e*(1 - 1/primen(i));
    end
end
e = floor(e);

同样,只要把prime集输出,就可以得到质数表。

输出的质数表

打印小于10000的质数表
>>    2     3     5     7    11    13    17    19    23    29 
>>   31    37    41    43    47    53    59    61    67    71 
>>   73    79    83    89    97   101   103   107   109   113 
>>  127   131   137   139   149   151   157   163   167   173 
>>  179   181   191   193   197   199   211   223   227   229 
>>  233   239   241   251   257   263   269   271   277   281 
>>  283   293   307   311   313   317   331   337   347   349 
>>  353   359   367   373   379   383   389   397   401   409 
>>  419   421   431   433   439   443   449   457   461   463 
>>  467   479   487   491   499   503   509   521   523   541 
>>  547   557   563   569   571   577   587   593   599   601 
>>  607   613   617   619   631   641   643   647   653   659 
>>  661   673   677   683   691   701   709   719   727   733 
>>  739   743   751   757   761   769   773   787   797   809 
>>  811   821   823   827   829   839   853   857   859   863 
>>  877   881   883   887   907   911   919   929   937   941 
>>  947   953   967   971   977   983   991   997  1009  1013 
>> 1019  1021  1031  1033  1039  1049  1051  1061  1063  1069 
>> 1087  1091  1093  1097  1103  1109  1117  1123  1129  1151 
>> 1153  1163  1171  1181  1187  1193  1201  1213  1217  1223 
>> 1229  1231  1237  1249  1259  1277  1279  1283  1289  1291 
>> 1297  1301  1303  1307  1319  1321  1327  1361  1367  1373 
>> 1381  1399  1409  1423  1427  1429  1433  1439  1447  1451 
>> 1453  1459  1471  1481  1483  1487  1489  1493  1499  1511 
>> 1523  1531  1543  1549  1553  1559  1567  1571  1579  1583 
>> 1597  1601  1607  1609  1613  1619  1621  1627  1637  1657 
>> 1663  1667  1669  1693  1697  1699  1709  1721  1723  1733 
>> 1741  1747  1753  1759  1777  1783  1787  1789  1801  1811 
>> 1823  1831  1847  1861  1867  1871  1873  1877  1879  1889 
>> 1901  1907  1913  1931  1933  1949  1951  1973  1979  1987 
>> 1993  1997  1999  2003  2011  2017  2027  2029  2039  2053 
>> 2063  2069  2081  2083  2087  2089  2099  2111  2113  2129 
>> 2131  2137  2141  2143  2153  2161  2179  2203  2207  2213 
>> 2221  2237  2239  2243  2251  2267  2269  2273  2281  2287 
>> 2293  2297  2309  2311  2333  2339  2341  2347  2351  2357 
>> 2371  2377  2381  2383  2389  2393  2399  2411  2417  2423 
>> 2437  2441  2447  2459  2467  2473  2477  2503  2521  2531 
>> 2539  2543  2549  2551  2557  2579  2591  2593  2609  2617 
>> 2621  2633  2647  2657  2659  2663  2671  2677  2683  2687 
>> 2689  2693  2699  2707  2711  2713  2719  2729  2731  2741 
>> 2749  2753  2767  2777  2789  2791  2797  2801  2803  2819 
>> 2833  2837  2843  2851  2857  2861  2879  2887  2897  2903 
>> 2909  2917  2927  2939  2953  2957  2963  2969  2971  2999 
>> 3001  3011  3019  3023  3037  3041  3049  3061  3067  3079 
>> 3083  3089  3109  3119  3121  3137  3163  3167  3169  3181 
>> 3187  3191  3203  3209  3217  3221  3229  3251  3253  3257 
>> 3259  3271  3299  3301  3307  3313  3319  3323  3329  3331 
>> 3343  3347  3359  3361  3371  3373  3389  3391  3407  3413 
>> 3433  3449  3457  3461  3463  3467  3469  3491  3499  3511 
>> 3517  3527  3529  3533  3539  3541  3547  3557  3559  3571 
>> 3581  3583  3593  3607  3613  3617  3623  3631  3637  3643 
>> 3659  3671  3673  3677  3691  3697  3701  3709  3719  3727 
>> 3733  3739  3761  3767  3769  3779  3793  3797  3803  3821 
>> 3823  3833  3847  3851  3853  3863  3877  3881  3889  3907 
>> 3911  3917  3919  3923  3929  3931  3943  3947  3967  3989 
>> 4001  4003  4007  4013  4019  4021  4027  4049  4051  4057 
>> 4073  4079  4091  4093  4099  4111  4127  4129  4133  4139 
>> 4153  4157  4159  4177  4201  4211  4217  4219  4229  4231 
>> 4241  4243  4253  4259  4261  4271  4273  4283  4289  4297 
>> 4327  4337  4339  4349  4357  4363  4373  4391  4397  4409 
>> 4421  4423  4441  4447  4451  4457  4463  4481  4483  4493 
>> 4507  4513  4517  4519  4523  4547  4549  4561  4567  4583 
>> 4591  4597  4603  4621  4637  4639  4643  4649  4651  4657 
>> 4663  4673  4679  4691  4703  4721  4723  4729  4733  4751 
>> 4759  4783  4787  4789  4793  4799  4801  4813  4817  4831 
>> 4861  4871  4877  4889  4903  4909  4919  4931  4933  4937 
>> 4943  4951  4957  4967  4969  4973  4987  4993  4999  5003 
>> 5009  5011  5021  5023  5039  5051  5059  5077  5081  5087 
>> 5099  5101  5107  5113  5119  5147  5153  5167  5171  5179 
>> 5189  5197  5209  5227  5231  5233  5237  5261  5273  5279 
>> 5281  5297  5303  5309  5323  5333  5347  5351  5381  5387 
>> 5393  5399  5407  5413  5417  5419  5431  5437  5441  5443 
>> 5449  5471  5477  5479  5483  5501  5503  5507  5519  5521 
>> 5527  5531  5557  5563  5569  5573  5581  5591  5623  5639 
>> 5641  5647  5651  5653  5657  5659  5669  5683  5689  5693 
>> 5701  5711  5717  5737  5741  5743  5749  5779  5783  5791 
>> 5801  5807  5813  5821  5827  5839  5843  5849  5851  5857 
>> 5861  5867  5869  5879  5881  5897  5903  5923  5927  5939 
>> 5953  5981  5987  6007  6011  6029  6037  6043  6047  6053 
>> 6067  6073  6079  6089  6091  6101  6113  6121  6131  6133 
>> 6143  6151  6163  6173  6197  6199  6203  6211  6217  6221 
>> 6229  6247  6257  6263  6269  6271  6277  6287  6299  6301 
>> 6311  6317  6323  6329  6337  6343  6353  6359  6361  6367 
>> 6373  6379  6389  6397  6421  6427  6449  6451  6469  6473 
>> 6481  6491  6521  6529  6547  6551  6553  6563  6569  6571 
>> 6577  6581  6599  6607  6619  6637  6653  6659  6661  6673 
>> 6679  6689  6691  6701  6703  6709  6719  6733  6737  6761 
>> 6763  6779  6781  6791  6793  6803  6823  6827  6829  6833 
>> 6841  6857  6863  6869  6871  6883  6899  6907  6911  6917 
>> 6947  6949  6959  6961  6967  6971  6977  6983  6991  6997 
>> 7001  7013  7019  7027  7039  7043  7057  7069  7079  7103 
>> 7109  7121  7127  7129  7151  7159  7177  7187  7193  7207 
>> 7211  7213  7219  7229  7237  7243  7247  7253  7283  7297 
>> 7307  7309  7321  7331  7333  7349  7351  7369  7393  7411 
>> 7417  7433  7451  7457  7459  7477  7481  7487  7489  7499 
>> 7507  7517  7523  7529  7537  7541  7547  7549  7559  7561 
>> 7573  7577  7583  7589  7591  7603  7607  7621  7639  7643 
>> 7649  7669  7673  7681  7687  7691  7699  7703  7717  7723 
>> 7727  7741  7753  7757  7759  7789  7793  7817  7823  7829 
>> 7841  7853  7867  7873  7877  7879  7883  7901  7907  7919 
>> 7927  7933  7937  7949  7951  7963  7993  8009  8011  8017 
>> 8039  8053  8059  8069  8081  8087  8089  8093  8101  8111 
>> 8117  8123  8147  8161  8167  8171  8179  8191  8209  8219 
>> 8221  8231  8233  8237  8243  8263  8269  8273  8287  8291 
>> 8293  8297  8311  8317  8329  8353  8363  8369  8377  8387 
>> 8389  8419  8423  8429  8431  8443  8447  8461  8467  8501 
>> 8513  8521  8527  8537  8539  8543  8563  8573  8581  8597 
>> 8599  8609  8623  8627  8629  8641  8647  8663  8669  8677 
>> 8681  8689  8693  8699  8707  8713  8719  8731  8737  8741 
>> 8747  8753  8761  8779  8783  8803  8807  8819  8821  8831 
>> 8837  8839  8849  8861  8863  8867  8887  8893  8923  8929 
>> 8933  8941  8951  8963  8969  8971  8999  9001  9007  9011 
>> 9013  9029  9041  9043  9049  9059  9067  9091  9103  9109 
>> 9127  9133  9137  9151  9157  9161  9173  9181  9187  9199 
>> 9203  9209  9221  9227  9239  9241  9257  9277  9281  9283 
>> 9293  9311  9319  9323  9337  9341  9343  9349  9371  9377 
>> 9391  9397  9403  9413  9419  9421  9431  9433  9437  9439 
>> 9461  9463  9467  9473  9479  9491  9497  9511  9521  9533 
>> 9539  9547  9551  9587  9601  9613  9619  9623  9629  9631 
>> 9643  9649  9661  9677  9679  9689  9697  9719  9721  9733 
>> 9739  9743  9749  9767  9769  9781  9787  9791  9803  9811 
>> 9817  9829  9833  9839  9851  9857  9859  9871  9883  9887 
>> 9901  9907  9923  9929  9931  9941  9949  9967  9973

防溢出

欧拉函数现在以及可以求出来啦,如果要求逆元的话,a^(φ(n) -1)一定是个特别大的数字。为了求最小的逆元,还有防止计算过程中求出来的数字太大,溢出,然后造成的数值误差,我们需要每次乘积的时候,都要对模n,进行取余运算。

这里把欧拉函数的值记为m,因为是φ(n) -1次幂,所以用m>2来限制。

A = a;
while(m > 2)
    A = mod(A*a , n);
    m = m - 1;
end

欧拉定理求逆元的代码

我再写代码的时候,出于个人习惯,写成了三个函数,第一个函数调用后两个的函数,最后输出的结果就是最小的正整数逆元。

function e = EULER_F_inv(a , n)
E = EULER_F(n);
e  = HIGH_POWER_INV(a , n , E);
%计算欧拉函数claculate the Euler function
function e = EULER_F(n)
isnot_prime = zeros(1 , n);%判断是否是合数
prime = [];%质数集
primen = [];%质因数集
if(n == 1)
    e = 1;
    return;
end
for i = 2:n
    if (isnot_prime(i) == 0)
        prime(end + 1) = i;
    end
    for j = 1 : length(prime)
        if((i*(prime(j))>n))
            break;
        end
        isnot_prime(i*(prime(j))) = 1;
        if(mod(i , prime(j)) == 0)
            break;
        end
    end
end
for k = 1:length(prime)
    if(mod(n , prime(k)) == 0)
        primen(end + 1) = prime(k);
    end
end
if(primen(length(primen)) == n)
    e = n-1;
else
    e = n;
    for i = 1 : length(primen)
        e = e*(1 - 1/primen(i));
    end
end
e = floor(e);
%高次幂的逆元计算
function f = HIGH_POWER_INV(e , n, nn)
E = e;
while(nn>2)
    E = mod(E*e , n);
    nn = nn - 1;
end
f = E;

接下来讲辗转相减法求逆元

辗转相减法求逆

这种方法是以前高中数学课堂上求公因数的更相减损术,也被称为欧几里得减法。

更相减损术

数学表达式:

a*x + b*y = 1  (a>b)

更相减损术和欧几里得算法的辗转相除法在形式上和逻辑上是类似的。但是也有很多地方不一样。

首先两钟方法的表达式是一样的,用的方法也都是迭代,除法可以看成是一次次减法的累积。

不同点在于,对于除法来说,mod(a , b)即a除以b的余数一定小于b,这样a永远是b,b一直是mod(a , b)。对于减法来说,每一次都要判断一下a - b和b的大小。

而且,a和a+b对于b的余数是一样的,这就意味着,当a小于b的时候,除法可以通过给a加上一定的b,从而可以通过迭代的方式求出a的逆,但是减法不可以。减法必须要求a>b。

同时,a和b迭代的方式会影响x和y的迭代公式,扩展欧几里得原理只有一套公式,但是辗转相除法有两套公式,并且什么时候用哪一套得基于判断。但是减法不同的,x和y的迭代公式中,没有a和b。

最后,两种方式的极限是不同的。除法的停止判断是b = 0 ,而减法的停止判断是a - b = 0;导致结束的式子,除法是a*x + 0*y = 1,那么a = 1 ,y = 0则是最小逆元的条件。但是对于减法,一般是这样的:1*x + 1*y = 1;那么最小逆元的条件是两个,要么x = 0,y = 1,要么x = 1,y = 0,无法确定是哪一种。至少我现在不知道,只是有一些猜测。

所以,用减法的优点是,从极限位置去推不需要记录每一步的a和b的取值,

缺点是,但是要记录a-b和b的大小,用来判断x和y的迭代方式,而且极限位置的x,y取值不确定,需要都算,然后最后检验,选择一个取值。同时只能有a>b的情况。

迭代式:

若b < a - b

an = an-1 - bn-1 , bn = bn-1;

xn = xn-1,yn = xn - xn-1;

若b > a - b

an = bn-1,bn = an-1 - bn-1;

xn = yn + yn-1,yn = xn-1;

从极限方向的推导式子:

b > a - b

xn-1 = yn

yn-1 = xn - yn

b < a - b

xn-1 = xn

yn-1 = yn - xn

所以要用减法的时候,需要先正向迭代,记录好b和a-b的关系,然后再从极限位置逆推,解出x,并选择正确的x。

辗转相减求逆代码

%欧几里得减法(辗转相减法)Must a>b;
function f = getinv1( a ,b)
A = a;
B = b;
sign = [];
x1 = 0;y1 = 1;i = 1;
while((a - b)~= 0)
    r = a - b;a = b;b = r;
    if(a < b)
        temp = b;b = a;a = temp;
        sign(end + 1) = 0;
    elseif(a > b)
        sign(end + 1) = 1;
    else
        sign(end + 1) = 0;
    end
    i = i + 1;
end
while(i ~= 1)
    if(sign(i-1) == 1)
        z = y1;
        y1 = x1 - y1;
        x1 = z;
    else
        y1 = y1 - x1;
    end
    i = i - 1;
end
while(x1<0)
    x1 = x1 + B;
end

sign = [];
x2 = 1;y2 = 0;i = 1;
a = A;b = B;
while((a - b)~= 0)
    r = a - b;a = b;b = r;
    if(a < b)
        temp = b;b = a;a = temp;
        sign(end + 1) = 0;
    elseif(a > b)
        sign(end + 1) = 1;
    else
        sign(end + 1) = 0;
    end
    i = i + 1;
end
while(i ~= 1)
    if(sign(i-1) == 1)
        z = y2;
        y2 = x2 - y2;
        x2 = z;
    else
        y2 = y2 - x2;
    end
    i = i - 1;
end
while(x2<0)
    x2 = x2 + B;
end
if(mod((a*x1) , b) == 1)
    f = x1;
else
    f = x2;
end

检验结果

对于代码正确性的检验

a = 1333
n = 25
r,inv = 22
a = 16754678
n = 199
r,inv = 47
a = 23
n = 13
r,inv = 4

小结

对于这几种求逆元的方式,小编没有去写详细的数学方面的证明和解释,只是简单的将这些理论拿来,用在了程序求解上。但是我希望读者可以通过我的文章,来了解更多的数学,对数学产生兴趣。

同样的,我也没有去特意说明每一种算法的时间复杂度和空间复杂度,只是简单介绍一下。

在四种求逆的方法中,除了辗转相减法,其他三种都可以计算a<n时的逆元,这个要记住啊。

这篇文章就到这里了,希望对你有所帮助。瑞斯拜。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

偶尔敲代码的创作猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值