zoukankan      html  css  js  c++  java
  • 【bzoj1009】[HNOI2008]GT考试(矩阵快速幂优化dp+kmp)

      题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1009

      这道题一看数据范围:$ n<=10^9 $,显然不是数学题就是矩乘快速幂优化dp。

      我们设$ f[i][j] $表示前$ i $位匹配不吉利数字$ j $位时的方案数,因为每一位的转移方式都是相同的,于是用kmp预处理出转移矩阵,直接矩乘快速幂就能过了。

    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iostream> 
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<map>
    #define ll long long
    #define ull unsigned long long
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define lowbit(x) (x& -x)
    #define inf 0x3f3f3f3f
    #define eps 1e-18
    #define maxn 100010
    inline ll read(){ll tmp=0; char c=getchar(),f=1; for(;c<'0'||'9'<c;c=getchar())if(c=='-')f=-1; for(;'0'<=c&&c<='9';c=getchar())tmp=(tmp<<3)+(tmp<<1)+c-'0'; return tmp*f;}
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline void swap(int &a,int &b){int tmp=a; a=b; b=tmp;}
    using namespace std;
    struct matrix{
        int size;
        int num[30][30];
    }ans;
    int nxt[30];
    char s[30];
    int n,m,mod;
    matrix mul(matrix a,matrix b)
    {
        matrix c; memset(&c,0,sizeof(c));
        c.size=a.size;
        for(int i=1;i<=a.size;i++)
            for(int j=1;j<=a.size;j++)
                for(int k=1;k<=a.size;k++)
                    c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j])%mod;
        return c;
    }
    matrix power(matrix a,ll b)
    {
        matrix ans; memset(&ans,0,sizeof(ans));
        ans.size=a.size;
        for(int i=1;i<=ans.size;i++)ans.num[i][i]=1;
        for(;b;b>>=1){
            if(b&1)ans=mul(ans,a);
            a=mul(a,a);
        }
        return ans;
    }
    int main()
    {
        n=read(); m=read(); mod=read();
        scanf("%s",s);
        nxt[1]=0; int tmp=0;
        for(int i=1;i<=m;i++){
            while(tmp&&s[i]!=s[tmp])tmp=nxt[tmp];
            if(s[i]==s[tmp])++tmp;
            nxt[i+1]=tmp;
        }
        for(int i=0;i<m;i++)
            for(int j='0';j<='9';j++){
                int tmp=i;
                while(tmp&&j!=s[tmp])tmp=nxt[tmp];
                if(j==s[tmp])++tmp;
                if(tmp<m)++ans.num[i+1][tmp+1];
            }
        ans.size=m;
        ans=power(ans,n);
        int tot=0;
        for(int i=1;i<=m;i++)
            tot+=ans.num[1][i];
        printf("%d
    ",tot%mod);
    }
    bzoj1009
  • 相关阅读:
    Codeforces Round #741 (Div. 2)部分题题解
    Wedding DJ题解 (回归OI)
    Note -「模板」FHQ-Treap
    Solution -「数论」「校内题」矩阵求和
    【游记】WC2021抱铃记
    洛谷 P7073 /AcWing 2769. 表达式
    洛谷 P3004 [USACO10DEC]Treasure Chest S/CSES 1097
    P7074 [CSP-J2020] 方格取数
    Unity Built-in转URP速查表
    英国学生签证准备材料+办理流程等
  • 原文地址:https://www.cnblogs.com/quzhizhou/p/9735693.html
Copyright © 2011-2022 走看看