• HNOI2008GT考试


    题目链接

    考虑dp,f(i,j)表示做到了第i位(共n位),当前的后缀串与A1~Aj相匹配 接下来的方案数。转移的话枚举一个k=0~9表示这位选什么,如果选了以后,匹配的位置会改变到 j' ,j'可以通过预处理A串的next数组(就是kmp里面的那个)然后不断向前跳得到,所以f(i,j) = ∑ f(i+1, j')。

    发现转移系数与i无关,因此可以用next数组处理出系数矩阵(长宽均为m),再做矩阵快速幂即可。

    复杂度O(m^3*logn)

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<queue>
    #define P puts("lala")
    #define cp cerr<<"lala"<<endl
    #define ln putchar('
    ')
    #define pb push_back
    #define fi first
    #define se second 
    #define mkp make_pair
    using namespace std;
    inline int read()
    {
        char ch=getchar();int g=1,re=0;
        while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
        while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
        return re*g;
    }
    typedef long long ll;
    typedef pair<int,int> pii;
    
    const int M=25;
    struct mat
    {
        int n,m;
        int s[M][M];
        mat() {clean();}
        void clean() {memset(s,0,sizeof(s));n=m=0;}
    };
    int mod;
    
    mat operator * (mat a,mat b)
    {
        mat c;
        c.n=a.n; c.m=b.m;
        for(int i=0;i<a.n;++i) for(int j=0;j<b.m;++j) for(int k=0;k<a.m;++k)
            c.s[i][j]=(c.s[i][j]+a.s[i][k]*b.s[k][j]%mod)%mod;
        return c;
    }
    mat fpm(mat a,int n)
    {
        mat ans;
        ans.n=ans.m=a.n;
        for(int i=0;i<a.n;++i) ans.s[i][i]=1;
        for(;n;n>>=1,a=a*a) if(n&1) ans=ans*a;
        return ans;
    }
    
    mat X,V;
    char s[M];
    int n,m,next[M];
    
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);freopen("1.out","w",stdout);
    #endif
        int i,j,opt,T;
        n=read();m=read();mod=read();
        scanf("%s",s+1);
        next[1]=0;
        int k=0;
        for(i=2;i<=m;++i)
        {
            while(k>0&&s[k+1]!=s[i]) k=next[k];
            if(s[k+1]==s[i]) k++;
            next[i]=k;
        }
        for(i=0;i<m;++i)
        {
            for(j=0;j<10;++j)
            {
                int k=i;
                while(k>0&&j!=s[k+1]-48) k=next[k];
                if(j==s[k+1]-48) k++;
                if(k<m) X.s[i][k]=(X.s[i][k]+1)%mod;
            }
        }
        X.n=X.m=m;
        V.n=m; V.m=1;
        for(i=0;i<m;++i) V.s[i][0]=1;
        X=fpm(X,n);
        X=X*V;
        printf("%d
    ",X.s[0][0]%mod);
        return 0;
    }
    /*
    
    */
  • 相关阅读:
    各种web页面中的绘图技术对比
    32位和64位操作系统
    mysql新建用户本地无法登录
    ruby libmysqlclient.18.dylib
    jenkins创建git任务连接时遇到的问题
    mybatis 打印日志log4j.properties
    使用shell统计出出现次数排名top10的网址(在博客园中没找到,特转一下)
    ActiveMQ和Tomcat的整合应用(转)
    java 哪些情况下会使对象锁释放
    Web容器与Servlet
  • 原文地址:https://www.cnblogs.com/thkkk/p/7994884.html
Copyright © 2020-2023  润新知