逆元を見つけるための3つの一般的な方法とnのStriling!の概算値

逆元:

定義:正の整数aの場合、ax≡1(mod m)がある場合、ここでの等号は恒等式を表すことに注意してください。この合同方程式の最小の正の整数解xは、mod mの逆元と呼ばれます(実際、x * x ^ -1 = 1のバリアントでは同等です。
逆元を見つけるために一般的に使用される3つの方法があります。拡張ユークリッドアルゴリズム、フェルマーの小定理、および逆元を見つけるためのオイラーの定理です。もちろん他の方法もありますが、以下では上記の3つだけを紹介します。

拡張ユークリッドアルゴリズム:
ユークリッドアルゴリズムは2つの数値の最大公約数を返し、拡張ユークリッドアルゴリズムは最大公約数を返しますが、渡すパラメーターはそれだけです。
定義:ax + by = gcd(a、b)(数論の知識に基づいてこの式の解が存在する必要があります)が
一般的に使用されるように、既知のa、bのxとyのセットを解くために使用されますモジュラー線形方程式と方程式グループを解きます。

xとyを解く方法の理解について:方程式ax + by = gcd(a、b)は既知です
(1)b = 0の場合、gcd(a、b)= a、次にx = 1、y = 0; 1 a + 0 b = a
(2)ax1 + by1 = gcd(a、b)とします。

次のexgcdbx2 +(a mod b)y2 = gcd(b、mod b)
Euclidの原理によれば、gcd(a、b)= gcd(b、mod b)、
次にax1 + by1 = bx2 +(a mod b)y2
は、ax1 + by1 = bx2 +(a-(a / b)* b)y2 = ay2 + bx2-(a / b)* by2を意味し、
x1 = y2、y1 = x2-(a / b)y2;
したがって、x1、y1の値はx2、y2に基づいていると結論付けることができます。

コード:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=200;
char s[N];
char b[N];

int exgcd(int a,int b,int &x,int &y)//扩展gcd
{
    if(!b)//b为0的情况
    {
        x=1;
        y=0;
        return a;
    }
    int r=exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*y;
    return r;
}


int main()
{

    ios::sync_with_stdio(false);
    int a,b;
    cin>>a>>b;
    int x=0,y=0;
    cout<<exgcd(a,b,x,y)<<endl;

    return 0;
}

1.拡張gcd逆元では、aとmが互いに素である必要があります

見つかった逆元は最小の逆元です

まず、互いに素の概念を示します。n個の数(n> = 2)の
公約数は1だけです。素数は素数とも呼ばれます。

最初に数学的プロセスを与えます:
ax + by = gcd(a、b);
次にax + my = gcd(a、m);
aとmは互いに素であるため、gcd(a、m)= 1
、次にax + my = 1
つまり
、この時点でのax≡1(mod m)xはaの逆数です。

コード:拡張gcdを使用してx、y、gcdのセットを検索します。gcdが1の場合、逆元が存在し、xを0〜m-1の範囲に調整します。それ以外の場合、逆元は存在しません。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=200;
char s[N];
char b[N];

int exgcd(int a,int b,int &x,int &y)
{
    if(a==0&&b==0)
        return -1;
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    int d=exgcd(b,a%b,y,x); //回代 注意这里的与扩展gcd的不同
    y-=a/b*x;
    return d;
}



int main()
{

    ios::sync_with_stdio(false);
    int m,n;
    cin>>m>>n;
    int x,y;
    int d=exgcd(m,n,x,y);
    cout<<(x%n+n)%n<<endl;

    return 0;
}

2.フェルマーの小定理では、mが素数である必要があり、aとmは互いに素です。

フェルマーの小定理:a ^(m-1)≡1(mod m)// mは素数
a ^(m-1)≡1(mod m)の場合、a * a ^(m-2)≡1( mod m)
したがって、a ^(m-2)は、mを法とする(高速電力で解かれる)
時間計算量logNの逆元です

コード:

int mod;
int quick_mod(int n,int p)
{
    int res=1,k=p;
    while(k)
    {
        if(k%2)
            res=res*n%mod;
        n=n*n%mod;
        k/=2;
    }
    return res;
}



int main()
{

    ios::sync_with_stdio(false);
    int a;
    cin>>a>>mod;
    cout<<quick_mod(a,mod-2)<<endl;
    return 0;
}

3.逆元のオイラーの定理:基本的な一般的な
時間計算量lg(√n)。

オイラーの定理:a ^(∅(m))≡1(mod m)
、a * a ^(∅(m)-1)≡1(mod m)
はax≡1(mod m)
なので、a ^(∅( M)-1)はaの逆数です∅(m)はm未満で互いに素な数の数です

1. n = 1の場合、φ(1)= 1です。1と任意の数(それ自体を含む)が互いに素な関係を構成する
ためです。2。素数pΦ(p)= p-1の場合、2つの素数pqの場合、Φ(pq)= pq-1
オイラー関数は乗法関数です。 、しかし、それは完全乗法的関数ではありません
。3。nが素数の特定の累乗である場合、つまりn = p ^ k(pは素数であり、kは1以上の整数)、その後のためここに写真の説明を書いてください
の例示φ(8)=φ(2 ^ 3)= 2 ^ 3-2 ^ 2 = 8 -4 = 4。
これは、数に素数pが含まれていない場合にのみ、nに対して互いに素になることができるためです。そして素数pを含む合計p (k-1)の、すなわち1×p、2×p、3×p、...、p(k-1)×pがあり、それらを削除し、残りはnは互いに素な数です。
上記の式は、次の形式でも記述
ここに写真の説明を書いてください
できます。4。nを2つの互いに素な整数、n = p1 * p2の積に分割できる場合
、Φ(n)=Φ(p1)*Φ(p2)
5 。数n(n> 1)は
ここに写真の説明を書いてください
、結論4に従って、一連の素数として積を記述
ここに写真の説明を書いてください
し、結論に従ってさらに3を与える
ここに写真の説明を書いてください
ことができます。ここに写真の説明を書いてください

オイラーの数を見つけるための2つのコードを以下に示します。

オイラーに直接尋ねる:

int euler(int x)
{
    int res=x;
    for(int i=2;i*i<=x;i++)
        if(x%i==0)
        {
            res=res/i*(i-1);
            while(x%i==0)
                x/=i;
        }
     if(x>1)
        res=res/x*(x-1);
     return res;
} 

テーブルを直接使用することもできます。プロセスでは、各phi [i] = iを作成し、各素数pについて、jはその倍数です。phi[j] = phi [j] / p *(p-1 );

void eulerplus()
{
    for(int i=1;i<=N;i++)
        phi[i]=i;
    for(int i=2;i<=N;i+=2)
        phi[i]/=2;
    for(int i=3;i<=N;i+=2)
        if(phi[i]==i)
    {
        for(int j=i;j<=N;j+=i)
            phi[j]=phi[j]/i*(i-1);
    }
}

4.逆元の適用モジュラ逆元
ax≡1(mod m)
so x = 1 / a(mod m)
so(b / a)mod m
then(b x)mod m
then(b%m
を見つけますx%m)%M

ストライリングフォーミュラ

多くの場合、nを要求するために使用されます!おおよその値
n!≈√2πn(n / e)^ n

エム、写真をアップロードしましょう
ここに写真の説明を書いてください

このナレッジポイントをlgと組み合わせて使用​​すると、数値
nの桁数x = logn(x)+ 1、
たとえば10進数の桁数x = lg(x)+1を見積もることができます。

ある数の階乗が別の数の倍数であると推定することもできます。

おすすめ

転載: blog.csdn.net/Puppet__/article/details/79220379