数论知识总结(乘法逆元,欧拉函数,线性筛,快速幂,快速乘等)

数论总结
内容:欧拉函数,欧拉定理,费马小定理,中国剩余定理,欧几里得定理,扩展欧几里得定理,逆元,线性筛、卡特兰数、快速幂、快速乘、矩阵乘法。

欧拉函数:A={ x | 1 < =x < n, gcd(x,n) = 1} 特殊的质数p的欧拉函数为p-1,
p的a次方的欧拉函数为p的a次方减p的a-1次方,可以在线性筛的过程中求出欧拉函数复杂度O(n)

代码为:

#include 
#include 
#include 
using namespace std;

const int N = 1000005;
int isnot[N], prime[N], n, ptot, phi[N];

void line_oula() {
    isnot[1] = 1;
    phi[1] = 1;
    for ( int i = 2; i <= n; i++ ) {
        if ( !isnot[i] ) prime[ptot++] = i, phi[i] = i - 1;
        for ( int t = 0; t < ptot; t++ ) {
            int j = prime[t] * i;
            if ( j > n ) break;
            isnot[j] = true;
            phi[j] = phi[prime[t]] * phi[i];//phi[nm]=phi[n]*phi[m] gcd(n,m) = 1
            if ( i % prime[t] == 0 ) {
                phi[j] = prime[t] * phi[i];//phi[p*i]=phi[p*p*k]=phi[k*p*p]=phi[k]*phi[p]*p=p*phi[i]
                break;
            }
        }
    }
}
int main() {
    scanf( "%d", &n );
    line_oula();
    for ( int i = 1; i <= n; i++ )
    cout << phi[i] << endl;
}

在求递推公式的时候分两种情况详见代码。

欧拉定理: 当gcd(a,n)=1时,
此定理的一个推论为费马小定理:当n取质数时

同时扩展而来可得逆元的多种求法:
逆元:ax≡1 (mod p),且gcd(a,p)=1(a与p互质),则称a关于模p的乘法逆元为x。
1、 用费马小定理:两边同乘a的逆元可得a的逆元为a的p-2次方mod p,
注意:此算法需要p为质数!一般用快速幂直接求得,此求法为欧拉定理的特殊化,当p不为质数时用欧拉定理即可两边同乘a的逆元,但需多算一个欧拉函数。
代码:略。
2、 用扩展欧几里得定理:设ax 除以p为t余数为1
则可得pt+1=ax化为方程为pt-ax=1方程可以用扩展欧几里得求出,
扩展欧几里得:d = gcd(a,b)可以表示为 d = ax + by
代码:略。
注意:此算法当p无需为质数
3、 用递推公式求得:令p = aq + r mod(p) 两边同乘a的逆元和r的逆元可得
a的逆元为负的r的逆元乘q mod (p)
代码为:

#include 
#include 
#include 
using namespace std;

const int N = 1000005;

int inva[N], n, p;

void inverse() {
    inva[1] = 1;
    for ( int i = 2; i <= n; i++ )
    inva[i] = ( -( p / i * inva[p%i] ) % p + p ) % p;
}

int main() {
    scanf( "%d%d", &n, &p );
    inverse();
    for ( int i = 1; i <= n ; i++ )
    cout << inva[i] << endl;
    return 0;
}

注意:此算法p必须为质数!!!

卡特兰数:递推公式h[1] = 1,h[n] = h[n-1] *(4*n-2)/(n+1)

快速幂
代码:

long long fpow( long long a, long long b )
{
    long long ans = 1;
    for ( ; b; b >>= 1, a = ( a%MOD * a%MOD ) % MOD )
    if ( b & 1 ) ans = (ans%MOD * a % MOD)%MOD;
    return ans;
}

快速乘:
代码:

long long fcheng( long long a, long long b )
{
    long long ans = 0;
    for ( ; b; b >>= 1,a = ( a%MOD + a%MOD ) % MOD )
    if ( b & 1 ) ans = (ans%MOD + a%MOD) % MOD;
    return ans;
}

你可能感兴趣的:(总结)