OI知识点汇总

UPD during 2018 4 17 to 2019 9 24 新增很多内容
UPD at 2018 4 16 [ 10:42 ] 降级FWT,新增「dp套dp」
UPD at 2018 3 24 [ 15:43 ] 新增部分内容,删除了「拟阵」
按照省选+ 难度 分级

数论

  • gcd,EXgcd
  • Lucas定理,扩展Lucas
  • 中国剩余定理,扩展中国剩余定理
  • 杨辉三角递推式(以及相关等式)
  • 卡特兰数h(n) = C(2n,n-1)/n
  • 错排D(n)=(n-1)(D(n-1)+D(n-2))
  • 原根
  • BSGS
  • 线性基
  • 高斯消元
  • 容斥原理(莫比乌斯容斥系数,二进制容斥,Min_Max容斥)
  • 快速幂,矩阵快速幂
  • 线性筛
  • 杜教筛, ∗ * 洲阁筛, ∗ * Min_25筛
  • FWT 位运算卷积
  • FFT&NTT 多项式卷积
  • ∗ * 子集卷积
  • 群论基础知识,置换群(Burnside引理 + polya计数)
  • Miller-Rabin大质数检验
  • Pollard rho大数分解质因数
  • ∗ * 单纯型
  • ∗ * 线性递推
  • ∗ * 差分表
  • ∗ * 多项式那一大堆
  • ∗ * 杨表(Young diagram)

信息学奥林匹克数学竞赛,真不是吹的
建议多看看各种数学书,多get一点技巧(离散数学,具体数学等等)

#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

const int mmod = 1e9 + 7 , N = 5000 ;
int C[5005][5005] , fac[100005] , inv[100005] , D[100005] ;

int p[1000005] , phi[1000005] , miu[1000005] , tao[1000005] , d[1000005] , topp ;
bool isnotp[1000005] ;
void get_P(){
	phi[1] = 0 ;
	miu[1] = 1 ;
	for( int i = 2 ; i <= 1000000 ; i ++ ){
		if( !isnotp[i] ){
			p[++topp] = i ;
			phi[i] = i - 1 ;
			miu[i] = -1 ;
			tao[i] = 2 , d[i] = 1 ;
		}
		for( int j = 1 ; j <= topp && i * p[j] <= 1000000 ; j ++ ){
			if( i % p[j] == 0 ){
				//i中包含 p[j] ,现在又多了一个 p[j]
				//也就是原来 i 和它互质的数,记为 k ,现在变成了 1*k,2*k,3*k...p[j]*k
				//而这些 1*k,2*k,3*k...p[j]*k 一定和 i*p[j]互质
				//http://blog.csdn.net/Lytning/article/details/24432651
				phi[ i*p[j] ] = phi[i] * p[j] ;
				//miu根据定义可得
				miu[ i*p[j] ] = 0 ;
				//num = p1^t1 + p2^t2 + ... + pn^tn ;
				//tao[num] = ( t1 + 1 ) * ( t2 + 1 ) * ... * ( tn + 1 ) ;
				//tao[ num*p[j] ] = tao[num] / ( d[i] + 1 ) * ( d[i] + 1 + 1 ) ;
				tao[ i*p[j] ] = tao[i] / ( d[i] + 1 ) * ( d[i] + 2 ) ;
				d[ i*p[j] ] = d[i] + 1 ;
				break ;
			}
			phi[ i*p[j] ] = phi[i] * phi[ p[j] ] ;
			miu[ i*p[j] ] = miu[i] * -1 ;
			tao[ i*p[j] ] = tao[i] * 2 ;
			d[ i*p[j] ] = 1 ;
		}
	}
}


//杨辉三角:C[i][j] = C[i-1][j] + C[i-1][j-1] 
void preWork_C() {
	C[0][0] = 1 ;
	for( int i = 1 ; i <= 5000 ; i ++ ) {
		C[i][0] = 1 ;
		for( int j = 1 ; j <= i ; j ++ )
			C[i][j] = ( C[i-1][j] + C[i-1][j-1] ) %mmod ;
	}
}

//阶乘:fac[i] = fac[i-1] * i 
void preWork_fac() {
	fac[0] = 1 ;
	for( int i = 1 ; i <= 100000 ; i ++ )
		fac[i] = 1LL * fac[i-1] * i %mmod ;
}

//错排公式:D[i] = ( i - 1 )*( D[i-1] + D[i-2] ) 
void preWork_cuopai() {
	D[1] = 0 ; D[2] = 1 ;
	for( int i = 3 ; i <= 100000 ; i ++ )
		D[i] = 1LL * ( i - 1 ) * ( D[i-1] + D[i-2] ) %mmod ;
}

//
int gcd( int a , int b ) {
	if( !b ) return a ;
	return gcd( b , a%b ) ;
}

//
long long exgcd( long long a , long long b , long long &x , long long &y ) {
	if( !b ) {
		x = 1 , y = 0 ;
		return a ;
	} else {
		long long xx , yy , d = exgcd( b , a%b , xx , yy ) ;
		x = yy , y = xx - a / b * yy ;
		return d ;
	}
}

//只有x和p互质时,才存在逆元 
int get_inv( int x , int p ) {
	long long inv , tmp ;
	exgcd( x , p , inv , tmp ) ;
	return ( inv %mmod + mmod ) %mmod ;
}

//同上,阶乘的逆元,用于算组合数 
void preWork_facinv() {
	inv[100000] = get_inv( fac[100000] , mmod ) ;
	for( int i = 99999 ; i >= 0 ; i -- )
		inv[i] = 1LL * inv[i+1] * ( i + 1 ) %mmod ;
}

//组合数: n! / m! / (n-m)! = n! * inv[m!] * inv[(n-m)!] 
int comb( int n , int m ){
	return 1LL * fac[n] * inv[m] %mmod * inv[n-m]%mmod ;
}

//卡特兰公式: C(2n,n-1)/n 
int catalan( int x ){
	return 1LL * comb( 2 * x , x - 1 ) * get_inv( x , mmod ) %mmod ;
}

//要求模数为质数 
long long Lucas( long long n , long long m ) {
	if( n < m ) return 0 ;
	if( n >= mmod )
		return Lucas( n/mmod , m/mmod ) * comb( n%mmod , m%mmod ) ;
	else return C[n][m] ;
}

//要求mi两两互质
//http://blog.csdn.net/clove_unique/article/details/54571216
void CRT(){
	int cnt , m[100] , c[100] ;
	long long M = 1 , ans = 0 ;
	scanf( "%d" , &cnt ) ;
	for( int i = 1 ; i <= cnt ; i ++ ){
		scanf( "%d%d" , &m[i] , &c[i] ) ;
		M *= m[i] ;
	}
	for( int i = 1 ; i <= cnt ; i ++ ){
		long long Mi = M / m[i] ;
		ans = ( ans + c[i] * Mi %mmod * get_inv( Mi , m[i] ) ) %mmod ;
	}
}

int main( int argc , char *argv[] ) {
	preWork_C() ;
	preWork_fac() ;
	preWork_facinv() ;
	get_P() ;
	return 0 ;
}

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

/*********************
 * BSGS
 * POJ 2417
 * to solve x that fit
 * B^x == N ( mod P )
 ********************/
int mmod , B , N ;
struct hashTable{
	int head[7333] , num[100005] , pw[100005] , pre[100005] , tp ;
	void init(){
		memset( head , 0 , sizeof( head ) ) ;
		tp = 0 ;
	}
	void Insert( int x , int k ){
		int id = x%7333 ;
		for( int i = head[id] ; i ; i = pre[i] )
			if( num[i] == x ) return ;
		pre[++tp] = head[id] ;
		num[ head[id] = tp ] = x ;
		pw[tp] = k ;
	}
	int Query( int x ){
		int id = x%7333 ;
		for( int i = head[id] ; i ; i = pre[i] )
			if( num[i] == x ) return pw[i] ;
		return 0 ;
	}
}HT ;

long long s_pow( long long x , long long b ){
	long long rt = 1 ;
	while( b ){
		if( b&1 ) rt = rt * x %mmod ;
		x = x * x %mmod ; b >>= 1 ;
	}
	return rt ;
}

int BSGS(){
	if( N == 1 && B != 0 ) return 0 ;
	int sqr = ceil( sqrt( mmod ) ) ;
	long long now = N , Bsqr = 1 ;
	for( int i = 1 ; i <= sqr ; i ++ ){
		now = now * B %mmod ; Bsqr = Bsqr * B %mmod ;
		if( Bsqr == N ) return i ;
		HT.Insert( now , i ) ;
	}
	now = Bsqr ;
	for( int i = 1 ; i <= sqr ; i ++ ){
		int tmp = HT.Query( now ) ;
		if( tmp ) return i * sqr - tmp ;
		now = now * Bsqr %mmod ;
	}
	return -1 ;
}

int main(){
	while( scanf( "%d%d%d" , &mmod , &B , &N ) != EOF ){
		HT.init() ;
		int tmp = BSGS() ;
		if( tmp == -1 ) puts( "no solution" ) ;
		else printf( "%d\n" , tmp ) ;
	}
}

图论

  • 桥,割点
  • 强连通分量(tarjan, ∗ * Kosaraju),点双连通分量
  • ∗ * 圆方树
  • dfs序,树链剖分,括号序,欧拉序
  • 倍增LCA,(另tarjan O(n)LCA)
  • 欧拉回路(Fleury算法),哈密顿回路
  • 最小生成树(Kruskal, ∗ * Prim, ∗ * Boruvka), ∗ * 曼哈顿距离(平面图)最小生成树, ∗ * 欧几里德距离最小生成树(算几)
  • Kruskal重构树
  • 最短路(dijkstra,floyd,SPFA),最短路径树
  • ∗ * K短路(堆维护非树边,不是A*)
  • 差分约束系统
  • ∗ * 单纯型
  • 二分图(染色)
  • 匈牙利算法(add:最小覆盖,最长反链,最小路径覆盖…), ∗ * KM算法
  • ∗ * 带花树
  • 网络流(add:最小割,最大权闭合子图,01分数规划),费用流,上下界网络流
  • 平面图转对偶图
  • 树的重心/直径
  • 拓扑排序
  • ∗ * 朱流算法(tarjan有一个nlog的实现)
  • 2-SAT
  • ∗ * prufer编码
  • Matrix-Tree定理
  • ∗ * 弦图(完美消除序列,MCS算法,Clique tree)

数据结构

  • 栈,队列(双端队列),链表(二维链表)
  • 并查集
  • ST表(RMQ, ∗ * O(n)RMQ )
  • 堆(手写堆,优先队列)
  • 平衡树(set,map,Treap ,Splay,替罪羊树)
  • 树状数组
  • 线段树(永久化标记, ∗ * ZKW线段树, ∗ * 李超线段树, ∗ * Segment-tree-Beats,线段树合并)
  • 可并堆(左偏树,斜堆)
  • 主席树
  • 分块,树分块(莫队,树上莫对)
  • 点分治,动态点分治
  • LCT, ∗ * ETT
  • ∗ * 跳表
  • ∗ * 猫树
  • 树套树( ∗ * 套树^n,n≥3)
  • ∗ * 可持久化数据结构

博弈论

  • NIM游戏
  • SG函数, ∗ * anti-SG
  • ∗ * alpha-beta 对抗搜索
  • 二分图博弈

关于NIM和SG,参见:zyf2000-关于 Nim游戏与SG函数 的一点研究

搜索

  • BFS
  • DFS
  • ∗ * 分支定界
  • 换顺序搜(倒着搜,斜着搜,随便乱搜)
  • A*
  • IDDFS
  • ∗ * alpha-beta 对抗搜索
  • ∗ * Bron–Kerbosch算法
  • ∗ * Dancing-Link

字符串

  • KMP
  • Hash
  • manacher
  • trie树
  • AC自动机(trie图,fail树)
  • 后缀数组
  • 后缀自动机
  • 回文自动机
  • 最小表示法
  • ∗ * Z-Algorithm
  • ∗ * 后缀平衡树
  • ∗ * Huffman编码

DP

  • 背包DP
  • 区间DP
  • 状压DP
  • 数位DP
  • 树形DP
  • 期望DP
  • 瞎JBDP
  • ∗ * 插头DP
  • ∗ * DP套DP(用一个DP来当另一个DP的状态)
  • 矩阵维护的动态dp
  • 单调队列优化
  • 斜率优化(斜率单调,二分斜率)
  • ∗ * 四边形优化
  • dp凸优化
  • 数据结构优化
  • ∗ * 针对石子合并的GarsiaWachs算法

计算几何

  • 向量基础运算(加减乘除,点乘叉乘,向量旋转等)
  • 直线求交点
  • 求多变形面积
  • 求多边形重心
  • 判断点在凸多边形内部
  • 凸包
  • 半平面交
  • 旋转卡壳
  • ∗ * 最小圆覆盖
  • 自适应simpson积分

其他

  • ∗ * 主定理(分析复杂度用的)
  • 二分答案
  • 补集转化
  • 倍增/二进制拆分
  • 差分/前缀和
  • 数据分治(根号分治, ∗ * 阈值法)
  • Hash
  • CDQ,整体二分,线段树分治
  • 贪心
  • 扫描线
  • 莫队
  • 离散化
  • 启发式合并
  • DSU on tree
  • 树链的并
  • ∗ * 模拟退火, ∗ * 爬山算法

一些比较散的知识点:

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值