• 字符串(String)


    字符串(String)

    为了庆祝祖国生日, 小Z学起了斐波那契数列。

    (F[0]=0)
    (F[1]=1)
    (F[i]=F[i-2]+F[i-1])

    小Z突发奇想, 要是这个 (F) 是一个 string 类型该多有趣。

    (S[0]=”0”)
    (S[1]=”1”)
    (S[i]=S[i-2]S[i-1]) (表示连接两个字符串)。

    小Z经过科学的计算后发现(S[N])会很长很长, 但是他只想知道一个问题的答案, 就是小Z心中的0/1串(T)(S[N])中出现了多少次。

    (P)

    Input

    第一行三个整数 (N,M,P,) (N) 如题中所述、 (M) 为串 (T) 的长度、 (P) 为需要取模的数。

    第二行为一个长度为 (M) 的 0/1 串。

    Output

    仅包含一个整数, 为出现次数模 (P) 之后的值。

    Example

    输入 #1

    (7) (3) (100)
    (101)

    输出 #1

    (8)

    Scoring

    对于 30%的数据,满足 (N≤20)
    对于 60%的数据,满足 (N≤10^5, M≤ܯ200)
    对于 100%的数据,满足 (N≤10^9, M≤10000,P≤10^9).

    比赛时候把正解想出来了其实(小声bb

    奈何基本功不过关,写挂了就拿了20分没啥好解释就是菜

    ——————————————————————————————————————————

    30分做法:

    暴力:/

    60分做法:

    把给定字符串叫str, 每次新合成的字符串是s[i],用一个数组p[i]在存储str在s[i]中的出现次数

    你在写暴力的过程中会注意到一个现象,那就是每次两段加起来之后,规定str在s[i]中的出现次数总是等于p[i-2]+p[i-1]+连接处的新出现次数

    那么我们每次只要判断新连接起来的部分有妹有str就好了,因此只要存s[i-2]的后m-1个和s[i-1]的前m-1个,然后看看加上新出现的次数就好了

    然后,奇怪的性质出现了

    0, 1, 01, 101, 01101, 10101101,0110110101101, ...

    (s[i-2].length()>= m-1) 时,我们把每次新连起来的部分提取出来

    这里以样例中的m=3为例

    0, 1, 01, 101, 01101, 10101101,0110110101101, 101011010110110101101, ...

    相隔的是相同的,可以自行证明一下(我讲不清楚

    那么只要把这两部分中str的次数分别算出来,就是一个递推式了

    [egin{cases} p[i]=p[i-1]+p[i-2]+e1 ext{if n 为奇数}\ p[i]=p[i-1]+p[i-2]+e2 ext{if n 为偶数}\ end{cases}]

    转换一下(i为奇数与偶数时,e1与e2代表的东西不同,但对化简结果不影响

    [egin{cases} p[i+1]=p[i]+p[i-1]+e1\ p[i]=p[i-1]+p[i-2]+e2\ end{cases}]

    下面式子带入上面的,得到

    [p[i+1]=(p[i-1]+p[i-2]+e2)+p[i-1]+e1 ]

    转化后得

    [p[i]=2*p[i-2]+p[i-3]+(e1+e2) ]

    因此拿60分的代码流程:

    前面暴力推字符串,推到(s[i].length()>=m) && (s[i-1].length()>=m)(s[i].length()=Fib[i], 增长的很快)

    然后截出两段连接处的字符串, 求出e1与e2

    快乐递推——

    打完一交,袜,TLE了

    100分做法:

    我不会

    一个递推式T了,咋办咯

    用矩阵快速幂被

    好了讲完了

    另:由于本人太菜还没订正出来,这里放上gs大佬的代码一份

    //%%%hgs%%%
    #include <bits/stdc++.h>
    int zjc;
    struct Matrix {
        int n, m, a[4][4];
        int *operator[](const int &x) { return a[x]; }
        Matrix() { memset(a, 0, sizeof(a)); }
        void set() { memset(a, 0, sizeof(a)); }
        void set(int _n, int _m) { n = _n; m = _m; memset(a, 0, sizeof(a)); }
        void Init() { memset(a, 0, sizeof(a)); for (int i = 0; i < m; i++) a[i][i] = 1; }
        friend Matrix operator * (Matrix &a, Matrix &b) {
            Matrix c; c.set(b.n, a.m);
            for (int i = 0; i < c.m; i++) {
                for (int j = 0; j < c.n; j++) {
                    for (int k = 0; k < a.n; k++) {
                        c[i][j] += 1ll * a[i][k] * b[k][j] % zjc;
                        if (c[i][j] >= zjc) { c[i][j] -= zjc; }
                    }
                }
            }
            return c;
        }
    } a, b, c, p, ret;
    int n, m;
    char M[20001];
    int nxt[20001];
    void getfail() {
        nxt[0] = -1;
        for (int i = 1, j = -1; M[i]; i++) {
            while (~j && M[i] != M[j + 1]) { j = nxt[j]; }
            if (M[i] == M[j + 1]) { ++j; }
            nxt[i] = j;
        }
    }
    int kmp(const char *s) {
        int cnt = 0;
        for (int i = 0, j = -1; s[i]; ++i) {
            while (~j && s[i] != M[j + 1]) { j = nxt[j]; }
            if (s[i] == M[j + 1]) { ++j; }
            if (j == m - 1) { ++cnt; j = nxt[j]; }
        }
        return cnt;
    }
    int fib[22]; // val is the len of string.
    std::string F[5];
    int num[5];
    int main() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(NULL);
        fib[0] = fib[1] = 1;
        for (int i = 2; i <= 21; i++) { fib[i] = fib[i - 2] + fib[i - 1]; }
        std::cin >> n >> m >> zjc >> M; getfail();
        int _first = 0; 
        for (int i = 0; i <= 21; i++)
            if (fib[i] >= m) { _first = i; break; 
        if (n < _first) { std::cout << 0 << '
    '; return 0; 
        F[0] = "0"; F[1] = "1";
        for (int i = 2; i <= _first + 4; i++) { F[i % 5] = F[(i - 2) % 5] + F[(i - 1) % 5]; }
        for (int i = 0; i < 5; i++) { num[i] = kmp(F[(_first + i) % 5].c_str()); }
        if (_first + 4 >= n) { std::cout << num[n - _first] % zjc << '
    '; return 0; }
        a.set(4, 4); a[0][0] = a[0][1] = a[1][0] = a[1][2] = a[3][3] = 1; a[3][0] = num[4] - num[3] - num[2];
        b.set(4, 4); b[0][0] = b[0][1] = b[1][0] = b[1][2] = b[3][3] = 1; b[3][0] = num[3] - num[2] - num[1];
        c.set(4, 1); c[0][0] = num[3], c[0][1] = num[2], c[0][2] = num[1], c[0][3] = 1;
        p = a * b; ret.set(p.m, p.m); ret.Init();
        int y = n - _first - 3 >> 1;
        while (y) {
            if (y & 1) { ret = ret * p; }       
            p = p * p; y >>= 1;
        }
        c = c * ret;
        if (n - _first - 3 & 1) { c = c * a; }
        std::cout << c[0][0] << '
    ';
        return 0;
    }
    

    大佬的blog

  • 相关阅读:
    3.2 机器学习基本算法
    《TensorFlow深度学习应用实践》
    基于element动态调整table高度
    关于小程序表单验证解决方案
    LHS与RHS
    小程序---获取地理位置及获取用户userinfo信息
    element----修改element中table里面的右侧滚动条样式
    关于微信里wx.getUserInfo获取用户信息都是拼音的转成中文方法
    element中upload单图片转base64后添加进数组,请求接口
    vue的生命周期
  • 原文地址:https://www.cnblogs.com/Sheffield/p/13358670.html
Copyright © 2020-2023  润新知