ACM Number Theary
Euclid
求最大公约数
#include<iostream>
using namespace std;
#define LL long long
LL GCD(LL A,LL B)
{
LL Temp;
while(B)
{
Temp=A%B;
A=B;
B=Temp;
}
return A;
}
求解线性不定方程
#include<iostream>
using namespace std;
#define LL long long
void Euclid(LL A,LL B,LL &D,LL &X,LL &Y)
{
if(!B)
{
D=A;
X=1;
Y=0;
}
else
{
Euclid(B,A%B,D,Y,X);
Y-=X*(A/B);
}
}
Quick Pow
求解大数乘法(M*N)%MOD
#include<iostream>
using namespace std;
#define LL long long
LL Muti(LL A,LL B,LL MOD)
{
LL Ans=0;
A=A%MOD;
B=B%MOD;
if(B<0)
{
A=-A;
B=-B;
}
while(B)
{
if(B&1)
Ans=(Ans+A)%MOD;
B>>=1;
A=(A+A)%MOD;
}
Ans=(Ans+MOD)%MOD;
return Ans;
}
快速求解数的N次幂
#include<iostream>
using namespace std;
#define LL long long
LL Pow(LL A,LL B,LL MOD)
{
LL Ans=1;
A=A%MOD;
B=B%(MOD-1);
while(B)
{
if(B&1)
Ans=Ans*A%MOD;
B=B>>1;
A=A*A%MOD;
}
return Ans;
}
快速求组合数
组合数取模
#include<iostream>
using namespace std;
LL Combine(LL N,LL M,LL MOD)
{
if(M>N)
return 0;
LL Ans=1;
for(int i=1;i<=M;i++)
{
LL X=(i)%MOD;
LL S=(N+1-i)%MOD;
X=Pow(X,MOD-2,MOD);
Ans=Ans*S%MOD*X%MOD;
}
return Ans;
}
LL Lucas(LL N,LL M,LL MOD)
{
if(M==0)
return 1;
return Lucas(N/MOD,M/MOD,MOD)*Combine(N%MOD,M%MOD,MOD)%MOD;
}
#include<iostream>
using namespace std;
#define LL long long
#define MAX 100010
LL Inverse[MAX];
LL JieC[MAX];
LL GetInverse()
{
LL Temp=1;
JieC[0]=1;
Inverse[0]=1;
for(int i=1;i<MAX;i++)
{
Temp=Temp*i%MOD;
JieC[i]=Temp;
Inverse[i]=Pow(Temp,MOD-2,MOD);
}
}
LL Combine(int N,int M)
{
if(N<M)
return 0;
LL Ans=1;
Ans=Ans*JieC[N]%MOD*Inverse[M]%MOD*Inverse[N-M]%MOD;
return Ans;
}
模方程
求解逆元
#include<iostream>
using namespace std;
#define LL long long
LL GetInv(LL A,LL MOD)
{
LL X,Y,D;
Euclid(A,MOD,D,X,Y);
if(D!=1)
return -1;
else
return (X%MOD+MOD)%MOD;
}
#include<iostream>
using namespace std;
#define LL long long
LL GetInv(LL A,LL MOD)
{
LL Ans;
Ans=Pow(A,MOD-2,MOD);
return Ans;
}
#include<iostream>
using namespace std;
#define LL long long
LL Inv[MAX];
void GetInv(LL MOD)
{
Inv[1]=1;
for(int i=1;i<MOD;i++)
Inv[i]=(MOD-MOD/i)*Inv[MOD%i]%MOD;
}
求解同余方程式
#include<iostream>
using namespace std;
#define LL long long
bool Merge(LL LA,LL MA,LL LB,LL MB,LL &RL,LL &RM)
{
LL Same=GCD(MA,MB);
LL Dis=LB-LA;
LL Ans;
if(Dis%Same)
return false;
Dis=(Dis%MB+MB)%MB;
MA/=Same;
MB/=Same;
Dis/=Same;
Ans=Dis*GetInv(MA,MB)%MB;
Ans=Ans*Same*MA;
Ans+=LA;
RM=MA*MB*Same;
RL=(Ans%RM+RM)%RM;
return true;
}
LL CRT(LL *L,LL *M,int N)
{
LL RL=L[1];
LL RM=M[1];
LL TL;
LL TM;
for(int i=2;i<=N;i++)
{
TL=RL;
TM=RM;
if(!Merge(TL,TM,L[i],M[i],RL,RM))
return -1;
}
return (RL%RM+RM)%RM;
}
大数测试
Miller_Rabin大素数测试
#define Turn 80
bool Miller_Rabin(LL N)
{
if(N==2||N==3||N==5||N==7||N==11)
return true;
if(N==1||!(N%2)||!(N%3)||!(N%7)||!(N%11))
return false;
LL Pre,X,U;
int R=0;
U=N-1;
while(!(U&1))
{
R++;
U>>=1;
}
srand(time(0));
for(int i=1;i<=Turn;i++)
{
X=rand()%(N-2)+2;
if(X%N==0)
continue;
X=Pow(X,U,N);
Pre=X;
int T=R;
if(X!=1)
{
while(T>0)
{
if(X==(N-1))
break;
X=Muti(X,X,N);
T--;
}
if(T<=0)
return false;
}
}
return true;
}
大数因数分解
#include<iostream>
#include<ctime>
#include<cstdlib>
using nameapace std;
LL Pollard_rho(LL N,LL C)
{
LL Rycle=2;
LL Time=1;
LL X,Y;
LL Same,Dis;
X=rand()%N;
Y=X;
while(true)
{
Time++;
X=(Muti(X,X,N)+C)%N;
if(Y==X)
return N;
Dis=X>Y?(X-Y):(Y-X);
Same=GCD(Dis,N);
if(Same!=1&&Same!=N)
return Same;
if(Time==Rycle)
{
Y=X;
Rycle*=2;
}
}
}
void Find(LL N)
{
if(Miller_Rabin(N))
{
Factor[Count++]=N;
return ;
}
LL P=N;
while(P>=N)
{
LL C=rand()%(N-1)+1;
P=Pollard_rho(P,C);
}
Find(P);
Find(N/P);
}
素数筛
诶氏筛法
#include<iostream>
using namespace std;
#define MAX 1000000
int Prime[MAX];
bool IsPrime[MAX];
int Count;
void GetPrime()
{
Count=1;
for(int i=2;i<MAX;i++)
{
if(!IsPrime[i])
{
for(int j=i+i;j<MAX;j+=i)
IsPrime[j]=true;
Prime[Count++]=i;
}
}
}
欧拉筛法
#include<iostream>
using namespace std;
#define MAX 1000000
int Prime[MAX];
bool IsPrime[MAX];
int Count;
void GetPrime()
{
Count=1;
for(int i=2;i<MAX;i++)
{
if(!IsPrime[i])
Prime[Count++]=i;
for(int j=1;j<Count&&Prime[j]*i<MAX;j++)
{
IsPrime[i*Prime[j]]=true;
if(i%Prime[j]==0)
break;
}
}
}