数论入门基础

一.辗转相除求最大公约数

a/b=p…q(q=a%b) -> a=b*p+q -> gcd(a,b)=gcd(b,q)
可持续递归下去直到后面的数为0

时间复杂度:**O(log max(a,b)),**底数为2.
若b>a:gcd(a,b)=gcd(b,a%b)=gcd(b,a);(一次变化为下述情况)。
若a>b:
(1)b>a/2,gcd(a,b)=gcd(b,a%b),a%b=a-b<a/2;
(2)b<a/2,gcd(a,b)=gcd(b,a%b),a%b<b<a/2;

综上,a每次都缩小1/2以上,故时间复杂度为O(log max(a,b))。
补充:lcm(a,b)(最小公倍数)=a*b/gcd(a,b)

int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}

二.扩展欧几里得算法

1.求解x,y满足ax+by=c

裴蜀定理(或贝祖定理):若a,b是整数,且gcd(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立。
重要推论:a,b互质的充分必要条件是存在整数x,y使ax+by=1.

请添加图片描述

n个整数间的裴蜀定理:设a1,a2,a3…an为n个整数,d是它们的最大公约数,那么存在整数x1…xn使得x1a1+x2a2+…xnan=d。
特别来说,如果a1…an存在任意两个数是互质的(不必满足两两互质),那么 存在整数x1… xn使得x1
a1+x2a2+ …xnan=1。证法类似两个数的情况。

请添加图片描述

//求解:ax+by=gcd(a,b);
int extgcd(int a,int b,int &x,int &y)
{
    int res=a;
    if(b!=0)
    {
        res=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else x=1,y=0;
    return res;
}

求得一组x,y后,可通过: (k为任意整数)
x’=x+(b/gcd)k
y’=y-(a/gcd)k
求得全部解。
在此基础上求解ax+by=c(c一定为gcd的整数倍)的全部解
x’=x(c/gcd)+(b/gcd)k
y’=y(c/gcd)-(a/gcd)k
注意:在ax+by=gcd的全部解的基础上都乘以 c/gcd会漏解。

2.求逆元

时间复杂度:O(logn),适用于mod很大,计算个数不多。

//求逆元
int extgcd(int a,int b,int &x,int &y)
{
    int res=a;
    if(b!=0)
    {
        res=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else x=1,y=0;
    return res;
}
ll getan(ll a)
{
    ll x,y;
    ll s=extgcd(a,mod,x,y);
    return s==1?(x%mod+mod)%mod:-1;
}

3.求同余式的解

同余定理:给定一个正整数m,如果两个整数a和b满足(a-b)能够被m整除即(a-b)/ m得到一个整数,那么就称整数a与b对模m同余,记作 a≡b(mod m)。(就相当于a%m=b%m)
消去律:若 gcd(c,p) = 1,则 ac ≡ bc mod p => a ≡ b mod p
反身性:a≡a (mod m)
对称性: 若a≡b(mod m),则b≡a(mod m)
传递性: 若a≡b(mod m),b≡c(mod m),则a≡c(mod m)
同余式相加减:若a≡b(mod m),b≡c(mod m),则a ± c≡b ± d(mod m)
同余式相乘:若a≡b(mod m),b≡c(mod m),则ac≡bd(mod m)
除法:若ac ≡ bc (mod m) c≠0 则 a≡ b (mod m/gcd(c,m)) 其中gcd(c,m)表示c,m的最大公约数。特殊地 ,gcd(c,m)=1 则a ≡ b (mod m)
幂运算
如果a ≡ b (mod m),那么a^n ≡ b^n (mod m)
若a ≡ b (mod m),n|m,则 a ≡ b (mod n)
若a ≡ b (mod mi) (i=1,2…n) 则 a ≡ b (mod [m1,m2,…mn]) 其中[m1,m2,…mn]表示m1,m2,…mn的最小公倍数

a x ≡ c (mod m)—>(ax-c)%m=0
则存在 ax-c=my,令y=-y -->c=ax+my会到上述问题1

三.素数

1.基础算法(素性测试,约数枚举,整数分解)

//时间复杂度均为O(log(x))

//素性测试
bool isprime(int x)
{
    if(x<=1)return false;
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0)return false;
    }
    return true;
}

 //约数枚举
void getyueshu(int x)
{
    vector<int>a;
    for(int i=1;i*i<=x;i++)
    {
        if(x%i==0)
        {
            a.push_back(i);
            if(x/i!=i)a.push_back(x/i);
        }
    }
    for(int i=0;i<a.size();i++)cout<<a[i]<<" ";
    cout<<"\n";
}

//整数分解
void getnum(int x)
{
    vector<int>a;
    for(int i=2;i*i<=x;i++)
    {
        while(x%i==0)
        {
            a.push_back(i);
            x=x/i;
        }
        if(x==1)break;
    }
    if(x!=1)a.push_back(x);
    for(int i=0;i<a.size();i++)cout<<a[i]<<" ";
    cout<<"\n";
}

2.素数筛

请添加图片描述

//时间复杂度O(n*loglogn)
int prime[1000010];
bool isprime[1000010];
int sieve(int n)
{
    int cnt=0;
    for(int i=0;i<=n;i++)isprime[i]=true;
    for(int i=2;i<=n;i++)
    {
        if(isprime[i])
        {
            prime[cnt++]=i;
            for(int j=i*2;j<=n;j+=i)isprime[j]=false;
        }
    }
    return cnt;
}
 
//时间复杂度O(n)
int prime[1000010];
bool isprime[1000010];
int sieve(int n)
{
    memset(isprime,true,sizeof(isprime));
    int cnt=0;
    for(int i=2;i<=n;i++)
    {
        if(isprime[i])prime[cnt++]=i;
        for(int j=0;j<cnt&&prime[j]*i<=n;j++)
        {
            isprime[prime[j]*i]=false;
            if(i%prime[j]==0)break;
        }
    }
    return cnt;
}

//区间筛法
bool isprime1[1000010];
bool isprime2[1000010];
int sieve(ll a,ll b)
{
    memset(isprime1,true,sizeof(isprime1));
    memset(isprime2,true,sizeof(isprime2));
    int cnt=0;
    for(ll i=2;i*i<b;i++)
    {
        if(isprime1[i])
        {
            for(ll j=2*i;j*j<b;j+=i)isprime1[j]=false;
            for(ll j=max(2LL,(a+i-1)/i)*i;j<b;j+=i)isprime2[j]=false;
        }
    }
    for(int i=2;i<b-a;i++)if(isprime2[i])cnt++;
    return cnt;
}

四.快速幂取模

//时间复杂度O(log n)
ll modpow(ll x,ll n,ll mod)
{
    ll res=1;
    while(n>0)
    {
        if(n&1)res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}

//时间复杂度O(log n)
ll modpow(ll x,ll n,ll mod)
{
    if(n==0)return 1;
    ll res=modpow(x*x%mod,n/2,mod);
    if(n&1)res=res*x%mod;
    return res;
}

五.欧拉函数

欧拉函数:就是对于一个正整数n,小于n且和n互质的正整数(包括1)的个数,记作φ(n) 。
欧拉函数的通式:φ(n)=n(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)……(1-1/pn)
其中p1, p2……pn为n的所有质因数,n是不为0的整数。φ(1)=1(唯一和1互质的数就是1本身)。
欧拉函数为积性函数,即:若m,n互质, φ ( m n ) = φ ( m ) ⋅ φ ( n ) 。

//欧拉函数计算
ll eular(ll n)
{
    ll res=n;
    for(int i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            res=res/i*(i-1);
            while(n%i==0)n=n/i;
        }
        if(n==1)break;
    }
    if(n>1)res=res/n*(n-1);
    return res;
}

//欧拉函数值打表 埃氏筛
int phi[1000010];
void euler_excel(int n)
{
    phi[1]=1;
    for(int i=2;i<=n;i++)phi[i]=0;
    for(int i=2;i<=n;i++)
    {
        if(!phi[i])
        {
            for(int j=i;j<=n;j+=i)
            {
                if(!phi[j])phi[j]=j;
                phi[j]=phi[j]/i*(i-1);
            }
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值