数论笔记
一,同余










二,欧几里得
ll gcd(ll a,ll b)
{
    if(a<b){ swap(a,b); }
    return b==0?a:gcd(b,a%b);
}
int lcm(int a,int b)
{
    return a*b/gcd(a,b);
}
扩展欧几里得:
LL exgcd(LL a,LL b,LL &d,LL &x,LL &y)
{
    if(!b){
        d=a,x=1,y=0;
    }
    else{
        exgcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}

ax+by=gcd(a,b)=d
三,线性素数筛选
const int maxn = 1e7+7;
int vis[maxn],prime[maxn];
int top;
void init()
{
    top=0;
    for(int i=2;i<maxn;i++)
    {
        if(!vis[i])
        {
            prime[top++]=i;
        }
        for(int j=0;prime[j]*i<maxn;j++)
        {
            vis[prime[j]*i]=1;
            if(i%prime[j]==0){
                break;
            }
        }
    }
}
四,欧拉函数


求单个数字的欧拉值
ll Euler(ll n)
{
    ll ans=n;
    for(int i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            ans=ans/i*(i-1);
            while(n%i==0){ n/=i; }
        }
    }
    if(n!=1){ ans=ans/n*(n-1); }
    return ans;
}
欧拉打表O(n)
using namespace std;
const int maxn = 3e6+7;
bool vis[maxn];
int prime[maxn/10];
int top;
long long euler[maxn];
void init()
{
    top=0;
    euler[1]=1;
    for(int i=2;i<maxn;i++)
    {
        if(!vis[i])
        {
            prime[top++]=i;
            euler[i]=i-1;
        }
        for(int j=0;j<top&&prime[j]*i<maxn;j++)
        {
            vis[prime[j]*i]=1;
            if(i%prime[j]==0)
            {
                euler[i*prime[j]]=euler[i]*prime[j];
                break;
            }
            else
            {
                euler[i*prime[j]]=euler[i]*(prime[j]-1);
            }
        }
    }
}
暴力打表复杂度O(nlogn)


                
            
        
浙公网安备 33010602011771号