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