数论总结

线性筛   求范围内质数

void Prime(int n)
{
    int i,j;
    for (i=2;i<=n;i++)
    {
        if (!not_prime[i]) prime[++cnt]=i;
        for (j=1;j<=cnt && i*prime[j]<=n;j++)
        {
            not_prime[i*prime[j]]=1;
            if (i%prime[j]==0) break;//保证每个数都是被最小质因子筛掉的 
        }
    }
}

快速幂   log(b)复杂度求解ab

int pow(int a,int k,int mod)
{
    int ans=1;
    while (k)
    {
        if (k&1) ans=1ll*ans*a%mod;
        a=1ll*a*a%mod;
        k>>=1;
    }
    return ans;
}
矩阵快速幂    用结构体存矩阵会方便一点
struct Mat
{
    int m[maxn][maxn];
}ans,a;
Mat mul(Mat a,Mat b,int n)
{
    int i,j,k;
    Mat c;
    memset(c.m,0,sizeof(c.m));
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    for(k=1;k<=n;k++)
        c.m[i][j]=(c.m[i][j]+1ll*a.m[i][k]*b.m[k][j]%mod)%mod;
    return c;
}
void Pow(Mat a,int k,int n)
{
    memset(ans.m,0,sizeof(ans.m));
    for(int i=1;i<=n;i++) ans.m[i][i]=1;
    while (k)
    {
        if (k&1) mul(ans,a,n);
        mul(a,a,n);
        k>>=1;
    }
}

欧几里得求最大公因数    gcd(m, n) = gcd(n, m mod n)

int gcd(int a,int b)
{
    if (b==0) return a;
    return gcd(b,a%b);
}
Theorem (裴蜀定理)
若 a 和 b 是整数,方程 ax+by=d 有整数解当且仅当 gcd(a, b) | d,即d是gcd(a,b)的倍数。
 

扩展欧几里得算法求解ax+by=gcd(a,b)    求出该方程的解x0,y0后,可知通解为x=x0+(b/gcd)*t    y=y0-(a/gcd)*t

#include<cstdio>
int exgcd(int a,int b,int& x,int& y)
{
    if (b==0)
    {
        x=1;y=0;
        return a;
    }
    int g=exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*y;
    return g;
}
int main()
{
    int a,b,x,y;
    scanf("%d%d",&a,&b);
    exgcd(a,b,x,y);
    printf("%d %d
",x,y);
    return 0; 
} 
同余的性质
如果 a1 ≡ b1(mod m)  , a2 ≡ b2(mod m)
那么 a1±a2 ≡ b1±b2(mod m)   ,  a1a2 ≡ b1b2(mod m)
 
逆元
对于(b/a)%p操作,我们只要找到一个x,0<=x<=p-1,使得ax ≡ 1(mod p),就可以用bx%p来表示(b/a)%p的值
我们将其中的x称为a的逆元,记作inv(a)
求逆元的方法
1、扩展欧几里得
ax ≡ 1(mod p)可以化为ax+tp=1,已知a,p即可求解x,t
2、快速幂
根据欧拉定理(费马小定理)有ap-1 ≡ 1(mod p) 即ap-2a ≡ 1(mod p)
所以inv(a)=ap-2%p
 
威尔逊定理
(p-2)! ≡ 1(mod p)   (p为质数)
原文地址:https://www.cnblogs.com/lsykk/p/13407932.html