欧几里得算法
用于求两整数的最大公倍数,其原理为,由于后者的a%b总是不断减小的,直至为0,所以当a%b=0时,gcd(a,b)=gcd(c,0),此时a和b的最大公约数就是c,其复杂度在以内。
int gcd(int a,int b){
if(b==0)return a;
return gcd (b,a%b);
}//递归写法
int gcd(int a,int b){
while(1){
int r=a % b;
a=b;
b=r;
if(b == 0) return a;//循环写法
}
}
扩展欧几里得算法
一个双六上有前后无限延续的格子,每个格子写有整数(可以想象为数列)。其中0号格子是起点,1号格子是终点,我们只能选则一个方向走a步或b步(a,b均为整数),所以根据a和b的值不同,我们有可能永远无法到达终点。
求一组可能的解,如果无解,输出-1
利用数学语言翻译,题意即求整数x和y使得ax+by=1。由欧几里得算法可以知道,当时,显然无解。反之,如果,那么就可以扩展欧几里得算法来求解
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;
}
快速幂
防止高次幂爆内存,优化幂运算,都应使用快速幂。
将幂级数转换为2进制数,通过将线性的幂级数变成平方数来快速的到幂的结果。
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;
x=x*x%mod;
n>>=1;
}
return res;
}
矩阵快速幂
有时候我们需要矩阵快速幂来加快运算,比如在计算斐波那契数列的时候,就可以通过矩阵的形式表达斐波那契数列,再用快速幂来加速运算,原理相同,只是将数改为矩阵,同时需要定义矩阵乘法。
定义矩阵及其乘法(取模与否按需处理)
typedef long long ll;
struct matrix{
ll m[N][N];
}
matrix operator * (const matrix a, const matrix b){
matrix res;
memset(res.m , 0 , sizeof(res.m));
for(int i = 0;i < N; i++ ){
for(int j = 0;j < N; j++ ){
for(int k = 0;k < N; K++ ){
res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j] % mod) % mod;
}
}
}
return res;
}
快速幂
matrix pow_matrix( matrix a , ll n ){
matrix ans;
memset(ans.m , 0 , sizeof(ans.m));
for(int i = 0;i < N; i++ )ans.m[i][i] = 1;
while(n > 0){
if(n & 1) ans = ans * a;
a = a * a;
n >>= 1;
}
return ans;
}
单调栈和单调队列
单调栈模板题洛谷
单调栈模板题Acwing
单调队列模板题Acwing
取出数列中/区间中条件最大值/最小值。