ACM算法模板(C++)--适用于ACM,蓝桥杯算法比赛

1.取消同步

ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

2.素数判断模板--简单方法、埃氏筛、欧拉筛

 2.1简单方法

bool is_prime(int x)
{
	if(x==1) return false;
	if(x==2) return true;
	else
	{
		for(int i = 2;i*i <= x;i++)
			if(x%i==0)	return false;
		return true;
	}
}

2.2埃氏筛

利用质因子进行,筛掉2,3,5,7...的倍数

const int N = 1e8;
bool is_prime[N+1];
for(int i = 2;i <= sqrt(n);i++)
{
	if(is_prime[i]==0)//代表是素数
	{
		for(int j = i*i;j <= n;j+=i)
		{
			is_prime[j] = 1;//不是素数
		}
	}
}

 2.3欧拉筛(比埃氏筛高效)

确保每个合数只被最小质因数筛掉,每个合数不会重复被筛去

const int N = 1e7;
int prime[N+1];
bool visit[N+1];
memset(visit,0,sizeof visit);
memset(prime,0,sizeof prime);
int cnt = 0;
for(int i = 2;i <= n;i++)
{
	if(!visit[i])
	{
		prime[cnt++] = i;
	}
	for(int j = 0;j < cnt;j++)
	{
		if(i * prime[j] > n)	break;
		visit[i * prime[j]] = 1;
		if(i % prime[j]==0)	break;
	}
}

3.字符串排序

#include <iostream> 
#include <bits/stdc++.h>
using namespace std;
string s[100];
int main()
{
	int n;
	cin>>n;
	for(int i = 0;i < n;i++)
		cin>>s[i];
	sort(s,s+n);
	for(int i = 0;i < n;i++)
		cout<<s[i];
	return 0;
}
//假如有三个字符串abc,bef,bcd,排序后就是abc,bcd,bef

 4.排序函数sqrt,sqrtl,sqrtf

sqrt()函数--适用于双精度数据,返回double类型
sqrtf()函数--适用于浮点型数据,返回float类型
sqrtl()函数--适用于长双进度类型,返回long double类型

5.优先队列--实现自动排序

从小到大:priority_queue<int,vector<int>,greater<int> >q;
从大到小:priority_queue<int>q;

优先队列每次讲优先级最高的元素先出队列

 题目讲解:https://www.luogu.com.cn/problem/P2085

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
priority_queue< int,vector<int>,greater<int> >q;
int n,m;
long long sum(int a,int b,int c)//(f(x) = ax^2+bx+c)
{
		for(int i = 1;i <= 100;i++)
		{
			long long sum;
			sum = a * i * i + b * i + c;
			q.push(sum);
		}
}
int main()
{
	cin>>n>>m;
	while(n--){
		int a,b,c;
		cin>>a>>b>>c;
		sum(a,b,c);
	}
	while(m--){
	cout<<q.top()<<" ";
	q.pop();
	}
	return 0;
}

6.字符串与数字的转换

字符串转化为数字:
int num = stoi(str);(转化为int)
int num = stol(str);(转化为long)
int num = stoll(str);(转化为longlong)
数字转化为字符串:
string str = to_string(num);

7.快速幂与矩阵快速幂

7.1快速幂

假设我们需要计算2^25次方,按照传统的方法需要计算25次,而对于快速幂算法只需要计算三次

25=1+8+16 00011001
1 00000001
8 00001000
16 00010000
long long fastpow(long long a,long long n,long long m)
{
	if(n == 0)	return 1;
	if(n == 1)	return a;
	long long temp = fastpow(a,n/2,m);
	if(n%2 == 1) return temp * temp * a % m;//奇数
	else return temp * temp % m;//偶数
}

7.2矩阵快速幂

题目:https://www.luogu.com.cn/problem/P3390

#include <iostream>
#include <bits/stdc++.h> 
using namespace std;
const int N = 110;
const int mod = 1e9+7;
long long n,k;
struct matrix
{
	long long m[N][N];//使用二维数组存储矩阵
};
matrix operator * (const matrix& a,const matrix& b)//重载乘法运算符以支持矩阵乘法
{
	matrix c;
	memset(c.m,0,sizeof(c.m));//初始化c矩阵
	for(int i = 0;i < N;i++)
	{
		for(int j = 0;j < N;j++)
		{
			for(int k = 0;k < N;k++)
			{
				c.m[i][j] = (c.m[i][j] + a.m[i][k]*b.m[k][j])%mod;
			}
		}
	}
	return c;
}
//* 外层循环变量`i`遍历结果矩阵`c`的行。  
//* 中层循环变量`j`遍历结果矩阵`c`的列。  
//* 内层循环变量`k`是中间变量,用于计算`a`的第`i`行和`b`的第`j`列的点积,即矩阵乘法的核心步骤。  
//* 在每次内层循环中,我们都将`a`的第`i`行第`k`列的元素与`b`的第`k`行第`j`列的元素相乘并将结果
//加到`c`的第`i`行第`j`列的元素上。注意,这里还使用了模数`mod`进行取模操作,以避免整数溢出。
int main()
{
	cin>>n>>k;
	matrix A;
	for(int i = 0;i < n;i++) 
	{
		for(int j = 0;j < n;j++)
		{
			cin>>A.m[i][j];
		}
	}
	matrix ans;
	memset(ans.m,0,sizeof(ans.m));
	for(int i = 0;i < n;i++)
	{
		ans.m[i][i] = 1;
	}
	while(k)
	{
		if(k&1)//奇数 
		{
			ans = ans * A;
		}
		A = A * A;
		k>>=1;
	}
	for(int i = 0;i < n;i++)
	{
		for(int j = 0;j < n;j++)
		{
			cout<<ans.m[i][j]<<" ";
		}
		cout<<endl;
	}
	return 0;
}

 8.阶乘之和1! + 2! + 3! + ... + n!

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int a[maxn],res[maxn];//a 被用来计算 i!,而 res 被用来存储所有阶乘的和。
int main()
{
	int n;
	cin>>n;
	a[0] = 1;//阶乘从1开始,所以 a[0] 初始化为1(代表1!),
	res[0] = 1;//res[0] 也初始化为1(代表1!的和)
	for(int i = 2;i <= n;i++)
	{
		int carry = 0;//判断进位
		for(int j = 0;j < maxn;j++)
		{
			a[j] = carry + a[j] * i;
			carry = a[j]/10;
			a[j]%=10;
		}
        //计算i的阶乘
		for(int j = 0;j < maxn;j++)
		{
			res[j] += a[j];
			res[j+1] += res[j]/10;
			res[j]%=10;
		}
        //将结果加到res中
	}
	int len = maxn;
	while(res[len-1]==0&&len>1)//去除前导0
	{
		len--;	
	}
	for(int i = len-1;i >= 0;i--)//逆序输出
	{
		cout<<res[i];
	}
	return 0;
} 

 9.进制转换

printf("%05o\n",35);    //按八进制格式输出,保留5位高位补零
printf("%03d\n",35);    //按十进制格式输出,保留3位高位补零
printf("%05x\n",35);    //按十六进制格式输出,保留5位高位补零

 9.1任意2-36进制数转化为10进制数

int Atoi(string s,int radix)    //s是给定的radix进制字符串
{
	int ans=0;
	for(int i=0;i<s.size();i++)
	{
		char t=s[i];
		if(t>='0'&&t<='9') ans=ans*radix+t-'0';//这个数小于10
		else ans=ans*radix+t-'A'+10;//这个是大于等于A
	}
	return ans;
}

 9.2将10进制数转换为任意的n进制数,结果为char型

string decimalToBase(int decimal, int base) {  
    string digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";  
    string result = "";  
    while (decimal > 0) {  
        result = digits[decimal % base] + result;  
        decimal /= base;  
    }  
    return result.empty() ? "0" : result;  
}  

9.3利用函数

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	cout<<n<<"的八进制为:"<<oct<<n<<endl;
	cout<<n<<"的十进制为:"<<dec<<n<<endl;
	cout<<n<<"的十六进制为:"<<hex<<n<<endl;
	cout<<n<<"的二进制为:"<<bitset<8>(n)<<endl;
	return 0;
}

10.辗转相除法与最小公倍数

辗转相除法:最大公因数
int gcd(int a int b)
{
	return b?gcd(b,a%b):a;
}
//或者直接利用函数    __gcd(a,b)
最小公倍数
int lcm(int a,int b)
{
	return a/gcd(a,b)*b;
}

11.高精度加减乘除

11.1高精度加法

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
string s1,s2;  //将所需要计算的数字以字符串的形式进行输入
int len1,len2,len;  //标记字符串的长度
int a[10005],b[10005];  //将字符串的每一位转化为数字,即将字符串转换为数字
int main()
{
	cin>>s1>>s2;
	len1 = s1.size(),len2 = s2.size();
	len = max(len1,len2);//选出更大的数的长度,再进行运算
	for(int i = 0;i < len1;i++)
	{
		a[i] = s1[len1 - i- 1] - '0';  //转化为数字
	}
	for(int i = 0;i < len2;i++)
	{
		b[i] = s2[len2 - i - 1] - '0';
	}
	for(int i = 0;i < len;i++)
	{
		a[i] = a[i] + b[i];  //将a[i] + b[i]的值赋值给a[i];
		a[i+1] = a[i+1] + a[i]/10;  //a[i+1]的值为当前的值加上进位的数,进位的数等于a[i]/10;
		a[i] %= 10;  //取余,每个数不超过10,前面已经将进位的数加上去了,直接取余就是结果
	}
	if(a[len]!=0&&len>0)  //a[len]!=0代表超出当前的位数,比如三位数加三位数可能为四位数,
                          //此时长度加1,最多也就加1,因为三位数加三位数不会为五位数
	{
		len++;
	}
	for(int i = len-1;i >= 0;i--)
	{
		cout<<a[i];
	}
	//逆序输出结果
	return 0;
}

11.2高精度减法

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
string s1,s2;
int a[10005],b[10005],c[10005];  //用c数组来存储结果
int len1,len2,len;
int flag = 0;  //用来标记是否需要负号
bool compare(string s1,string s2)  //两个字符串进行大小比较
{
	int len1 = s1.size(),len2 = s2.size();
	if(len1!=len2)  //两个字符串不相等
	{
		if(len1>len2)  //s1>s2就return true
			return true;
		else
			return false;
	}
    //两个字符串相等
	for(int i = 0;i < len1;i++)
	{
		if(s1[i]!=s2[i])
		{
			if(s1[i] > s2[i])  //s1>s2就return true
				return true;
			else
				return false;
		}
	}
	return true;  //两个字符串完全相等
}
int main()
{
	cin>>s1>>s2;
	if(!compare(s1,s2))//s2>s1
	{
		flag = 1;  //负号 
		s1.swap(s2);  //将两个字符串交换
	}
	len1 = s1.size(),len2 = s2.size();
	len = max(len1,len2);  //选出那个较长的字符串
	for(int i = 0;i < len1;i++)
	{
		a[i] = s1[len1-i-1] - '0';  //将字符转换为数字
	}
	for(int i = 0;i < len2;i++)
	{
		b[i] = s2[len2-i-1] - '0';
	}
	for(int i = 0;i < len;i++)
	{
		if(a[i] < b[i])  //借位运算
		{
			a[i+1]--;
			a[i] = a[i] + 10;
		}
		c[i] = a[i] - b[i];
	}
	while(c[len-1]==0&&len>1)  //去除前导0
	{
		len--;
	}
	if(flag==1)  //flag==1输出负号
	{
		cout<<"-";
	}
	for(int i = len-1;i >= 0;i--)
	{
		cout<<c[i]; //逆序输出结果
	}
	return 0;
}

 11.3高精度乘法

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
string s1,s2;
int a[10005],b[10005],c[10005];
int len1,len2,len;
int main()
{
	cin>>s1>>s2;
	len1 = s1.size(),len2 = s2.size();
	len = len1 + len2;//两个数相乘结果最长为len1+len2,如两位数与两位数相乘最大结果为四位数
	for(int i = 0;i < len1;i++)
	{
		a[i] = s1[len1-1-i] - '0';    
	}
	for(int i = 0;i < len2;i++)
	{
		b[i] = s2[len2-1-i] - '0';
	}
	for(int i = 0;i < len1;i++)
	{
		for(int j = 0;j < len2;j++)
		{
			c[i+j] += a[i] * b[j];
		}
	}
	int x = 0;
	for(int i = 0;i < len;i++)
	{
		c[i] += x;
		x = c[i]/10;
		c[i] %= 10;
	}
	while(c[len-1]==0&&len>1)
	{
		len--;
	}
	for(int i = len-1;i>=0;i--)
	{
		cout<<c[i];
	}
	return 0;
}

11.4高精度除法

高精度/低精度
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
string s1;
long long b;
long long a[10005],c[10005];
long long len;
long long d = 0;
int main()
{
	cin>>s1;
	cin>>b;
	len = s1.size();
	for(int i = 0;i < len;i++)
	{
		a[i] = s1[len-1-i] -  '0';
	}
	for(int i = len-1;i >= 0;i--)
	{
		d = d*10 + a[i];
		c[i] = d / b;
		d %= b;
	}
	while(c[len]==0&&len>0)
	{
		len--;
	}
	for(int i = len;i >= 0;i--)
	{
		cout<<c[i];
	}
	return 0;
}
高精/高精
#include <stdio.h>
#include<string.h>
char arra[20000] = { 0 }, arrb[20000] = { 0 };//分别储存a,b的值
int ans[20000] = { 0 };//储存商
int judge(char* arr1, char* arr2, int len)//判断是否可以相减的函数
{
    if (arr1[len] >'0') return 1; //如果arr1比arr2长, 则可以除 
    for (int i = len - 1; i >= 0; i--) {//从arr的最高位开始与arr2比较 
        if (arr1[i] > arr2[i]) return 1;//相同位时arr1中的数字更大,则可以相除
        else if (arr1[i] < arr2[i]) return 0;//相同位时arr1数字更小则不能相除
    }
    return 1;//arr1和arr2完全一样,可以相除 
}
void my_reverse(char* arr, int len)//翻转函数
{
    for (int i = 0; i < len - 1; i++, len--)
    {
        char temp = arr[i];
        arr[i] = arr[len - 1];
        arr[len - 1] = temp;
    }
}
void print_div(int len1, int len2, char* arr1, char* arr2, int* ans)
{
    for(int i = len1-len2;i>=0;i--)//从最高位开始
    {
        while (judge(arr1 + i, arr2, len2))//判定是否可以相减
        {
            for (int j = 0; j < len2; j++)//高精度减法
            {
                if (arr1[i + j] < arr2[j])
                {
                    arr1[i + j + 1] -= 1;
                    arr1[i + j] += 10;
                }
                arr1[i + j] -= (arr2[j] - '0');
            }
            ans[i]++;//ans[i]不可能>10
        }
    }
    int len_ans = len1 - len2;//ans的长度
    while (arr1[len1] == '0' && len1 > 0) len1--;//去掉前缀无用的零 
    while (ans[len_ans] == 0 && len_ans > 0) len_ans--;
    for (int i = len_ans; i >= 0; i--)//打印商
    {
        printf("%d", ans[i]);
    }
    printf("\n");
    //如果想要得到余数,则直接打印arr1即可,此时arr1存储的正是余数需要余数直接把下面的注释消掉即可
    //if (len1 > 0||arr1[0]>='0')
    //  for (int i = len1 - 1; i >= 0; i--)
    //      printf("%c", arr1[i]);
}
int main()
{
    scanf("%s %s", arra, arrb);
    int lena = strlen(arra);//计算a和b的长度
    int lenb = strlen(arrb);
    my_reverse(arra, lena);
    my_reverse(arrb, lenb);
    print_div(lena, lenb, arra, arrb, ans);
    return 0;
}

 优化算法--傅里叶实现高精度乘法

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
const double PI = acos(-1.0);
struct Complex {
  double x, y;
  Complex(double _x = 0.0, double _y = 0.0) {
    x = _x;
    y = _y;
  }
  Complex operator-(const Complex &b) const {
    return Complex(x - b.x, y - b.y);
  }
  Complex operator+(const Complex &b) const {
    return Complex(x + b.x, y + b.y);
  }
  Complex operator*(const Complex &b) const {
    return Complex(x * b.x - y * b.y, x * b.y + y * b.x);
  }
};
/*
 * 进行 FFT 和 IFFT 前的反置变换
 * 位置 i 和 i 的二进制反转后的位置互换
 *len 必须为 2 的幂
 */
void change(Complex y[], int len) {
  int i, j, k;
  for (int i = 1, j = len / 2; i < len - 1; i++) {
    if (i < j) std::swap(y[i], y[j]);
    // 交换互为小标反转的元素,i<j 保证交换一次
    // i 做正常的 + 1,j 做反转类型的 + 1,始终保持 i 和 j 是反转的
    k = len / 2;
    while (j >= k) {
      j = j - k;
      k = k / 2;
    }
    if (j < k) j += k;
  }
}
/*
 * 做 FFT
 *len 必须是 2^k 形式
 *on == 1 时是 DFT,on == -1 时是 IDFT
 */
void fft(Complex y[], int len, int on) {
  change(y, len);
  for (int h = 2; h <= len; h <<= 1) {
    Complex wn(cos(2 * PI / h), sin(on * 2 * PI / h));
    for (int j = 0; j <
1 图论 3 1.1 术语 3 1.2 独立集、覆盖集、支配集之间关系 3 1.3 DFS 4 1.3.1 割顶 6 1.3.2 桥 7 1.3.3 强连通分量 7 1.4 最小点基 7 1.5 拓扑排序 7 1.6 欧拉路 8 1.7 哈密顿路(正确?) 9 1.8 Bellman-ford 9 1.9 差分约束系统(用bellman-ford解) 10 1.10 dag最短路径 10 1.11 二分图匹配 11 1.11.1 匈牙利算法 11 1.11.2 KM算法 12 1.12 网络流 15 1.12.1 最大流 15 1.12.2 上下界的网络的最大流 17 1.12.3 上下界的网络的最小流 17 1.12.4 最小费用最大流 18 1.12.5 上下界的网络的最小费用最小流 21 2 数论 21 2.1 最大公约数gcd 21 2.2 最小公倍数lcm 22 2.3 快速幂取模B^LmodP(O(logb)) 22 2.4 Fermat小定理 22 2.5 Rabin-Miller伪素数测试 22 2.6 Pollard-rho 22 2.7 扩展欧几里德算法extended-gcd 24 2.8 欧拉定理 24 2.9 线性同余方程ax≡b(mod n) 24 2.10 中国剩余定理 25 2.11 Discrete Logging(BL == N (mod P)) 26 2.12 N!最后一个不为0的数字 27 2.13 2^14以内的素数 27 3 数据结构 31 3.1 堆(最小堆) 31 3.1.1 删除最小值元素: 31 3.1.2 插入元素和向上调整: 32 3.1.3 堆的建立 32 3.2 并查集 32 3.3 树状数组 33 3.3.1 LOWBIT 33 3.3.2 修改a[p] 33 3.3.3 前缀和A[1]+…+A[p] 34 3.3.4 一个二维树状数组的程序 34 3.4 线段树 35 3.5 字符串 38 3.5.1 字符串哈希 38 3.5.2 KMP算法 40 4 计算几何 41 4.1 直线交点 41 4.2 判断线段相交 41 4.3 三点外接圆圆心 42 4.4 判断点在多边形内 43 4.5 两圆交面积 43 4.6 最小包围圆 44 4.7 经纬度坐标 46 4.8 凸包 46 5 Problem 48 5.1 RMQ-LCA 48 5.1.1 Range Minimum Query(RMQ) 49 5.1.2 Lowest Common Ancestor (LCA) 53 5.1.3 Reduction from LCA to RMQ 56 5.1.4 From RMQ to LCA 57 5.1.5 An<O(N), O(1)> algorithm for the restricted RMQ 60 5.1.6 An AC programme 61 5.2 最长公共子序列LCS 64 5.3 最长上升子序列/最长不下降子序列(LIS) 65 5.3.1 O(n^2) 65 5.3.2 O(nlogn) 66 5.4 Joseph问题 67 5.5 0/1背包问题 68 6 组合数学相关 69 6.1 The Number of the Same BST 69 6.2 排列生成 71 6.3 逆序 72 6.3.1 归并排序求逆序 72 7 数值分析 72 7.1 二分法 72 7.2 迭代法(x=f(x)) 73 7.3 牛顿迭代 74 7.4 数值积分 74 7.5 高斯消元 75 8 其它 77
ACM 算法模板集 Contents 一. 常用函数与STL 二. 重要公式与定理 1. Fibonacci Number 2. Lucas Number 3. Catalan Number 4. Stirling Number(Second Kind) 5. Bell Number 6. Stirling's Approximation 7. Sum of Reciprocal Approximation 8. Young Tableau 9. 整数划分 10. 错排公式 11. 三角形内切圆半径公式 12. 三角形外接圆半径公式 13. 圆內接四边形面积公式 14. 基础数论公式 三. 大数模板,字符读入 四. 数论算法 1. Greatest Common Divisor最大公约数 2. Prime素数判断 3. Sieve Prime素数筛法 4. Module Inverse模逆元 5. Extended Euclid扩展欧几里德算法 6. Modular Linear Equation模线性方程(同余方程) 7. Chinese Remainder Theorem中国余数定理(互素于非互素) 8. Euler Function欧拉函数 9. Farey总数 9. Farey序列构造 10. Miller_Rabbin素数测试,Pollard_rho因式分解 五. 图论算法 1. 最小生成树(Kruscal算法) 2. 最小生成树(Prim算法) 3. 单源最短路径(Bellman-ford算法) 4. 单源最短路径(Dijkstra算法) 5. 全源最短路径(Folyd算法) 6. 拓扑排序 7. 网络预流和最大流 8. 网络最小费用最大流 9. 网络最大流(高度标号预流推进) 10. 最大团 11. 二分图最大匹配(匈牙利算法) 12. 带权二分图最优匹配(KM算法) 13. 强连通分量(Kosaraju算法) 14. 强连通分量(Gabow算法) 15. 无向图割边割点和双连通分量 16. 最小树形图O(N^3) 17. 最小树形图O(VE) 六. 几何算法 1. 几何模板 2. 球面上两点最短距离 3. 三点求圆心坐标 4. 三角形几个重要的点 七. 专题讨论 1. 树状数组 2. 字典树 3. 后缀树 4. 线段树 5. 并查集 6. 二叉堆 7. 逆序数(归并排序) 8. 树状DP 9. 欧拉路 10. 八数码 11. 高斯消元法 12. 字符串匹配(KMP算法) 13. 全排列,全组合 14. 二维线段树 15. 稳定婚姻匹配 16. 后缀数组 17. 左偏树 18. 标准RMQ-ST 19. 度限制最小生成树 20. 最优比率生成树(0/1分数规划) 21. 最小花费置换 22. 区间K大数 23. LCA - RMQ-ST 24. LCA – Tarjan 25. 指数型母函数 26. 指数型母函数(大数据) 27. 单词前缀树(字典树+KMP) 28. FFT(大数乘法) 29. 二分图网络最大流最小割 30. 混合图欧拉回路 31. 无源汇上下界网络流 32. 二分图最小点权覆盖 33. 带约束的轨道计数(Burnside引理) 34. 三分法求函数波峰 35. 单词计数,矩阵乘法 36. 字符串和数值hash 37. 滚动队列,前向星表示法 38. 最小点基,最小权点基
1 图论 3 1.1 术语 3 1.2 独立集、覆盖集、支配集之间关系 3 1.3 DFS 4 1.3.1 割顶 6 1.3.2 桥 7 1.3.3 强连通分量 7 1.4 最小点基 7 1.5 拓扑排序 7 1.6 欧拉路 8 1.7 哈密顿路(正确?) 9 1.8 Bellman-ford 9 1.9 差分约束系统(用bellman-ford解) 10 1.10 dag最短路径 10 1.11 二分图匹配 11 1.11.1 匈牙利算法 11 1.11.2 KM算法 12 1.12 网络流 15 1.12.1 最大流 15 1.12.2 上下界的网络的最大流 17 1.12.3 上下界的网络的最小流 17 1.12.4 最小费用最大流 18 1.12.5 上下界的网络的最小费用最小流 21 2 数论 21 2.1 最大公约数gcd 21 2.2 最小公倍数lcm 22 2.3 快速幂取模B^LmodP(O(logb)) 22 2.4 Fermat小定理 22 2.5 Rabin-Miller伪素数测试 22 2.6 Pollard-rho 22 2.7 扩展欧几里德算法extended-gcd 24 2.8 欧拉定理 24 2.9 线性同余方程ax≡b(mod n) 24 2.10 中国剩余定理 25 2.11 Discrete Logging(BL == N (mod P)) 26 2.12 N!最后一个不为0的数字 27 2.13 2^14以内的素数 27 3 数据结构 31 3.1 堆(最小堆) 31 3.1.1 删除最小值元素: 31 3.1.2 插入元素和向上调整: 32 3.1.3 堆的建立 32 3.2 并查集 32 3.3 树状数组 33 3.3.1 LOWBIT 33 3.3.2 修改a[p] 33 3.3.3 前缀和A[1]+…+A[p] 34 3.3.4 一个二维树状数组的程序 34 3.4 线段树 35 3.5 字符串 38 3.5.1 字符串哈希 38 3.5.2 KMP算法 40 4 计算几何 41 4.1 直线交点 41 4.2 判断线段相交 41 4.3 三点外接圆圆心 42 4.4 判断点在多边形内 43 4.5 两圆交面积 43 4.6 最小包围圆 44 4.7 经纬度坐标 46 4.8 凸包 46 5 Problem 48 5.1 RMQ-LCA 48 5.1.1 Range Minimum Query(RMQ) 49 5.1.2 Lowest Common Ancestor (LCA) 53 5.1.3 Reduction from LCA to RMQ 56 5.1.4 From RMQ to LCA 57 5.1.5 An algorithm for the restricted RMQ 60 5.1.6 An AC programme 61 5.2 最长公共子序列LCS 64 5.3 最长上升子序列/最长不下降子序列(LIS) 65 5.3.1 O(n^2) 65 5.3.2 O(nlogn) 66 5.4 Joseph问题 67 5.5 0/1背包问题 68 6 组合数学相关 69 6.1 The Number of the Same BST 69 6.2 排列生成 71 6.3 逆序 72 6.3.1 归并排序求逆序 72 7 数值分析 72 7.1 二分法 72 7.2 迭代法(x=f(x)) 73 7.3 牛顿迭代 74 7.4 数值积分 74 7.5 高斯消元 75 8 其它 77
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值