辗转相除法(Euclidean algorithm)
这个不用说了吧
代码:
int gcd(int a,int b)
{
if(b==0) return a;
return gcd(b,a%b);
}
扩展欧几里得算法(Extended Eucilde algorithm)
其实一开始我想把它叫扩展辗转相除法的…
用来“求整数x 和 y 使ax+by=1”。ax+by=1 有整数解的前提是gcd(a,b)=1.
也可以用 来求 ax+by=gcd(a,b),和上面的一样.
int extgcd(int a,int b,int &x,int &y)是求解该方程的函数,返回值是gcd(a,b).
思路是当 b=0的时候, a1 *1+b1 * 0=gcd(a1,b1) .对应的x=1,y=0,而 ax+by = gcd(a,b).一定可以化成a1 * 1+b1 *0=gcd(a1,b1).
代码:
int extgcd(int a,int b, int &x,int &y)
{
int d =a;
if(b!=0)
{
d=extgcd(b,a%b,y,x);
y-=(a/b)*x;
}
else
{
x=1;
y=0;
}
return d;
}
埃式筛法
用来判断多个数是否为素数。
代码:
int prime[MAXN-N];//第i个素数
bool is_prime[MAX_N+1];// is_prime[i] 为ture表示i是素数
int sieve(int n)
{
int p=0;
for(int i=0; i<=n; i++) is_prime[i]=true;
is_prime[0]=is_prime[1]=false;
for(int i=2; i<=n; i++)
{
if(is_prime[i])
{
prime[p++]=i;
for(int j=2*i; j<=n; j+=i) is_prime[j]=false;
}
}
return 0;
}
区间筛法
用来求 [a,b) 内有的素数。
b 以内的合数的 最小质因数一定不超过根号b, 用[ 2, 根号b) 的素数表和[ a,b) 的表,然后从[2,根号b) 的表中筛到素数的同时,也将其倍数从[ a , b) 的表中划去。
typedef long long ll;
bool is_prime[MAX_L];
bool is_prime_small[MAX_SORT_B];
void seqment_sieve(ll a,ll b)//is_prime[i-a]=true, 说明i是素数
{
for(ll int i=0; i*i<b; i++) is_prime_small[i]=true;
for(ll int i=0; i<b-a; i++) is_prime[i]= true;
for(ll int i=2; i*i<b; i++)
{
if(is_prime_small[i])
{
for(ll int j=2*i; j*j<b; j+=i)
{
is_prime_small[j]=false;
}
for(ll j =max(2LL, ((a+i-1)/i)*i; j<b; j+=i) is_prime[j-a]=false; 筛(a,b)
}
}
}
快速幕
用来求X的N次方,就是把N用二进制表示,然后相乘
typedef long long ll;
ll mod_pow(ll x,ll n, ll mod)
{
ll res=1;
while(n>0)
{
if(n&1) res=res*x%mod;//如果二进制该位为1,则乘上x^(2^i)
x=x*x%mod;
n>>=1;
}
return res;
}
欧拉函数打表
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int N=1000006;
int phi[N],m[N],p[N],nump;
int main()
{
int n=10000;
phi[1]=1;
for(int i=2; i<=n; i++)
{
if(!m[i])
{
p[++nump]=i;
phi[i]=i-1;
}
for(int j=1; j<=nump&&p[j]*i<=n; j++)
{
m[p[j]*i]=1;
if(i%p[j]==0)
{
phi[p[j]*i]= phi[i]*p[j];
break;
}
else phi[p[j]*i]=phi[i]*(p[j]-1);
}
}
printf("%d %d\n",phi[7],phi[12]);
return 0;
}
求单个数的欧拉值
#include<stdio>
#include<cstdlib>
int eular(int n)
{
int ret=1,i;
for(i=2; i*i<=n; i++)
{
if(n%i==0)
{
n/=i;
ret*=i-1;
while(n%i==0) n/=i,ret*=i;
}
}
if(n>1) ret*=(n-1);
return ret;
}
int mian()
{
int a;
scanf("%d",&a);
printf("%d",eular(a));
return 0;
}
∑ gcd(i,n) (1<= i<=n)
void getxgcd()
{
ll ans=1;
for(ll i=2; i*i<=n; i++)
{
if(n%i==0)
{
cnt=0,tmp=1;
while(n%i==0)
{
n/=i;
cnt++;
tmp*=i;
}
ans*=(cnt*i-cnt+i)*(tmp/i);
}
}if(n!=1) ans*=2*n-1;
printf("%lld\n",ans);
}
打表∑ ∑ gcd( j , i ) (1<=i<=n)(i+1<=j<=n)
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=4000006;
int flag[N+1];
int phi[N+1];
int p[N+1];
ll f[N+1]; // 储存∑gcd(i,n) (1<=i<=n)
ll ans[N+1]; //储存∑ ∑ gcd( j , i ) (1<=i<=n)(i+1<=j<=n)
int pnum=0; //素数数目
void getphi()
{
phi[1]=1;
for(int i=2; i<=N; i++)
{
if(!flag[i])
{
p[++pnum]=i;
phi[i]=i-1;
}
for(int j=1; j<=pnum && p[j]*i<=N; j++)
{
flag[p[j]*i]=1;
if(i%p[j]==0)
{
phi[p[j]*i]=phi[i]*p[j];
break;
}
phi[p[j]*i]=phi[i]*(p[j]-1);
}
}
for(int i=1 ;i<=N; i++)
{
for(int j=i*2; j<=N; j+=i)
{
f[j]+=i*phi[j/i];
}
}
for(int i=1; i<=N; i++)
{
ans[i]=ans[i-1]+f[i];
}
}
int main()
{
getphi();
printf("%lld\n",ans[100]);
return 0;
}