一,同余

 

 

 二,欧几里得

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)