GDOI2021游记

I.考前抱佛jio记

Talk is cheap show me the code.

I.I 字符串系列

I.I.I Hash

想必是不用说了。

I.I.II 前缀函数与 Knuth-Morris-Pratt 算法

I.I.II.I 计算前缀函数

算法1:枚举

复杂度\(\Theta(n^3)\)

vector<int> prefix_function(char *s){
    int n = strlen(s+1);
    vector<int> pi(n);
    for(int i=1; i<=n; i++){
        for(int j=i; j>=0; j--){
            bool flag = 1;
            for(int k=1; k<=j; k++){
                if(str[k] != str[i-k+1]){
                    flag = 0;
                    break;
                }
            }
            if(flag){
                pi[i] = j;
                break;
            }
        }
    }
    return pi;
}
优化1:相邻前缀函数至多增加1

复杂度\(\Theta(n^2)\)

vector<int> prefix_function(char *s){
    int n = str(s+1);
    vector<int> pi(n);
    for(int i=1; i<=n; i++){
        for(int j=pi[i-1]+1; j>=0; j--){
            bool flag = 1;
            for(int k=1; k<=j; k++){
                if(str[k] != str[i-k+1]){
                    flag = 0;
                    break;
                }
            }
            if(flag){
                pi[i] = j;
                break;
            }
        }
    }
    return pi;
}
优化2:失配指针

复杂度\(\Theta(n)\)

vector<int> prefix_function(char *s){
    int n = str(s+1);
    vector<int> pi(n);
    for(int i=1; i<=n; i++){
        int j = pi[i-1];
        while(j and s[i] != s[j+1]) j = pi[j-1];
        if(s[i] == s[j+1]) j ++;
        pi[i] = j;
    }
    return pi;
}

I.I.II.II Knuth-Morris-Pratt algorithm

复杂度\(\Theta(n+m)\)

vector<int> Knuth_Morris_Pratt_algorithm(char *s, char *p){
    int n = str(s+1), m = str(p+1);
    vector<int> pos, nxt;
    nxt = prefix_function(char *p);
    for(int i=1, j=0; i<=n; i++){
        while(j and s[i] != p[j+1]) j = nxt[j];
        if(p[j+1] == s[i]) j ++;
        if(j == m) pos.push_back(i-j+1);
    }
    return pos;
}

(字符串系列未完待续,咕咕咕~)

I.II 数学系列

I.II.I 从快速幂开始

int qpow(int x, int y){
    int cnt = 1, basic = x;
    while(y){
        if(y&1) cnt = cnt*basic;
        basic = basic*basic, y >>= 1;
    }
    return cnt;
}
矩阵类
struct Matrix
{
    int a[maxn][maxn], n;
    void clear(int x)
    {
        n = x;
        for (int i = 1; i <= n; i++)
            a[i][i] = 1;
    }
    void init(int x)
    {
        n = x;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                a[i][j] = 0;
    }
    Matrix operator*(const Matrix &x) const
    {
        Matrix c;
        c.init(n);
        for (int k = 1; k <= n; k++)
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= n; j++)
                    (c.a[i][j] += a[i][k] * x.a[k][j] % mod) %= mod;
        return c;
    }
    void debug()
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
                cout << a[i][j] << " ";
            cout << endl;
        }
    }
};

I.II.II 从gcd开始

int gcd(int x, int y){
    if(y == 0) return x;
    return gcd(y, x%y);
}

I.II.III 扩展欧几里得EX-gcd

定理:裴蜀定理

\[ax+by=\gcd(a,b) \]

简单推导:

\[ax+by=(a,b)=(b,a\%b)=bx'+(a\%b)y'=bx'+(a-b\cdot\left\lfloor \dfrac{a}{b}\right\rfloor)y'\\\therefore \begin{cases}x=y'\\y=x'-\left\lfloor\frac{a}{b}\right\rfloor y'\end{cases} \]

posted @ 2021-04-09 21:45  __allenge  阅读(105)  评论(0编辑  收藏  举报