OI知识点汇总

UPD during 2018 4 17 to 2018 5 17 新增部分内容

UPD at 2018 4 16 [ 10:42 ] 降级FWT,新增「dp套dp」

UPD at 2018 3 24 [ 15:43 ] 新增部分内容,删除了「拟阵」

UPD at 2018 3 20 [ 7:28 ] 按照省选+ 难度 调整了分级

UPD at 2017 12 29 [ 18:47 ] 新增部分内容,按照省选- NOIP+难度 调整了分级

UPD at 2017 11 28 [ 17:13 ] 新增部分内容

数论

  • gcd,EXgcd
  • Lucas定理,扩展Lucas
  • 中国剩余定理,扩展中国剩余定理
  • 杨辉三角递推式(以及相关等式)
  • 卡特兰数h(n) = C(2n,n-1)/n
  • 错排D(n)=(n-1)(D(n-1)+D(n-2))
  • 原根
  • BSGS
  • 线性基
  • 高斯消元
  • 容斥原理(莫比乌斯容斥系数,二进制容斥,各种容斥)
  • 快速幂,矩阵快速幂
  • 线性筛(欧拉函数,莫比乌斯函数,约数个数函数, 各种积性函数)
  • 狄利克雷卷积的应用
  • 杜教筛, 洲阁筛
  • FWT 位运算卷积
  • FFT&NTT 多项式卷积
  • 子集卷积
  • 生成函数(母函数)
  • 群论基础知识,Burnside引理 + polya计数
  • 仿射变换
  • Miller-Rabin大质数检验
  • Pollard rho大数分解质因数
#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分数规划),费用流,上下界网络流
  • 平面图转对偶图
  • 树的重心/直径
  • 拓扑排序
  • 朱流算法
  • 2-SAT
  • prufer编码
  • Matrix-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
  • 单调队列优化
  • 斜率优化(斜率单调,二分斜率)
  • 四边形优化
  • 数据结构优化
  • 针对石子合并的GarsiaWachs算法

计算几何

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

其他

  • 主定理(分析复杂度用的)
  • 二分答案(最大/小值),三分单峰函数
  • 逆向思维
  • 倍增思想
  • 差分(比如:询问[L,R]转化为[1,R]-[1,L],树上差分)
  • 前缀和(数组前缀和,树上到根前缀和)
  • WQS二分
  • 数据分治
  • Hash
  • CDQ,整体二分,线段树分治
  • 贪心
  • 扫描线(BZOJ1227可以简单感受一下)
  • 莫队
  • 离散化
  • 启发式合并
  • 仙人掌图问题
  • 模拟退火, 爬山算法
  • 迭代

一些比较散的知识点:

猜你喜欢

转载自blog.csdn.net/izumi_hanako/article/details/78482321