zoukankan      html  css  js  c++  java
  • BZOJ1009

    题目

    阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。
    他的不吉利数字A1A2... Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am。(A1和X1可以为0)

    题解

    看到题目,很自然地就能想到可以用数位dp来解决。但是这题位数太大,不能直接计算(写题的时候被这个限制卡了qwq)。
    对于很大的位数,可以考虑用矩阵加速。只要dp转移式是个一次多项式,就可以矩阵加速。
    设dp[i][p]为当前在第i位时,匹配到的不吉利的数字长度为p+1。
    预处理一个f[p][d]代表不吉利数字位置p后添加数字d到达的位置,这个可以用kmp预处理。然后套矩阵快速幂即可。

    #include <bits/stdc++.h>
    
    #define endl '
    '
    #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
    #define FILE freopen(".//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout)
    #define FI freopen(".//data_generator//in.txt","r",stdin)
    #define FO freopen("res.txt","w",stdout)
    #define pb push_back
    #define mp make_pair
    #define seteps(N) fixed << setprecision(N) 
    typedef long long ll;
    
    using namespace std;
    /*-----------------------------------------------------------------*/
    
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    #define INF 0x3f3f3f3f
    
    const int N = 50;
    const double eps = 1e-5;
    
    int nt[N];
    int f[N][N];
    char s[N];
    int k;
    
    struct Mat {
        int n;
        int arr[N][N];
        Mat(int n, int v) : n(n){
            if(v)
                for(int i = 0; i < n; i++) {
                    for(int j = 0; j < n; j++) {
                        arr[i][j] = (i == j);
                    }
                }
            else 
                for(int i = 0; i < n; i++) {
                    for(int j = 0; j < n; j++) {
                        arr[i][j] = 0;
                    }
                }
        }
        Mat operator*(Mat & rhs) {
            Mat tmp(n, 0);
            for(int i = 0; i < n; i++) {
                for(int j = 0; j < n; j++) {
                    for(int kk = 0; kk < n; kk++) {
                        tmp.arr[i][j] += (arr[i][kk] * rhs.arr[kk][j]) % k;
                        tmp.arr[i][j] %= k;
                    }
                }
            }
            return tmp;
        }
        Mat(const Mat & rhs) {
            n = rhs.n;
            for(int i = 0; i < n; i++) {
                for(int j = 0; j < n; j++) {
                    arr[i][j] = rhs.arr[i][j];
                }
            }
        }
        void print() {
            for(int i = 0; i < n; i++) {
                for(int j = 0; j < n; j++) {
                    cout << arr[i][j] << " ";
                }
                cout << endl;
            }
        }
    };
    
    Mat qpow(Mat a, int b) {
        Mat res(a.n, 1);
        while(b) {
            if(b & 1) res = res * a;
            a = a * a;
            b = b >> 1;
        }
        return res;
    }
    
    
    void getnext() {
        int i = 0, j = -1;
        int n = strlen(s);
        nt[i] = j;
        while(s[i]) {
            if(j == -1 || s[i] == s[j]) {
                i++, j++;
                nt[i] = j;
            } else {
                j = nt[j];
            }
        }
        for(int p = 0; p <= n; p++) {
            for(int i = 0; i <= 9; i++) {
                int tar = p;
                if(s[tar] - '0' == i) {
                    f[p][i] = tar + 1;
                } else {
                    f[p][i] = nt[p] < 0 ? 0 : f[nt[p]][i];
                }
            }
        }
    }
    
    
    int main() {
        IOS;
        int n, m;
        cin >> n >> m >> k;
        cin >> s;
        getnext();
        Mat ans(m, 0);
        for(int p = 0; p < m; p++) {
            for(int d = 0; d <= 9; d++) {
                ans.arr[f[p][d]][p]++;
            }
        }
        ans = qpow(ans, n);
        int res = 0;
        for(int i = 0; i < m; i++) {
            res += ans.arr[i][0];
            res %= k;
        }
        cout << res << endl;
    }
    
  • 相关阅读:
    LeetCode 258 Add Digits
    LeetCode 231 Power of Two
    LeetCode 28 Implement strStr()
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 21 Merge Two Sorted Lists
    LeetCode 20 Valid Parentheses
    图形处理函数库 ImageTTFBBox
    php一些函数
    func_get_arg(),func_get_args()和func_num_args()的用法
    人生不是故事,人生是世故,摸爬滚打才不会辜负功名尘土
  • 原文地址:https://www.cnblogs.com/limil/p/13502283.html
Copyright © 2011-2022 走看看