一,同余










二,欧几里得
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)
