zoukankan      html  css  js  c++  java
  • 一本通1646GT 考试

    1646:GT 考试

    时间限制: 1000 ms         内存限制: 524288 KB

    【题目描述】

    阿申准备报名参加 GT 考试,准考证号为 n 位数 X1X2Xn(0Xi9),他不希望准考证号上出现不吉利的数字。

    他的不吉利数字 A1A2Am(0Ai9) 有 m 位,不出现是指 X1X2Xn 中没有恰好一段等于 A1A2Am ,A1和 X1 可以为 0。

    【输入】

    第一行输入 n,m,K,接下来一行输入 m 位的数。

    【输出】

    阿申想知道不出现不吉利数字的号码有多少种,输出模 K 取余的结果。

    【输入样例】

    4 3 100 
    111

    【输出样例】

    81

    【提示】

    数据范围与提示:

    对于全部数据,1n109,1m20,2K1000

    sol:此题应该是先想到暴力的做法再用矩阵乘法优化的

    所以暴力的思想很重要

    dp[i][j]表示到第i位,匹配了j个的方案数

    先预处理出f[i][j]表示已经匹配了i个,加一个数字变成匹配了j个方案数,i,j<=m-1,用kmp搞搞

    转移就不难了,dp[i][j]+=dp[i-1][k]*f[k][j],是不是很像矩阵乘法2333

    #include <bits/stdc++.h>
    using namespace std;
    typedef int ll;
    inline ll read()
    {
        ll s=0;
        bool f=0;
        char ch=' ';
        while(!isdigit(ch))
        {
            f|=(ch=='-'); ch=getchar();
        }
        while(isdigit(ch))
        {
            s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
        }
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0)
        {
            putchar('-'); x=-x;
        }
        if(x<10)
        {
            putchar(x+'0'); return;
        }
        write(x/10);
        putchar((x%10)+'0');
        return;
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) write(x),putchar('
    ')
    const int N=100005,M=25;
    int n,m,Mod;
    int Num[25],f[25][25];
    int dp[N][M];
    inline void Ad(int &x,int y)
    {
        x+=y;
        x-=(x>=Mod)?Mod:0;
        return;
    }
    int Next[25];
    inline void Pre_f()
    {
        int i,j=0;
        Next[1]=0;
        for(i=2;i<=m;i++)
        {
            while((Num[j+1]!=Num[i])&&j) j=Next[j];
            if(Num[j+1]==i) j++;
            Next[i]=j;
        }
        for(i=0;i<m;i++)
        {
            for(j=0;j<=9;j++)
            {
                int Now=i;
                while((Num[Now+1]!=j)&&Now) Now=Next[Now];
                if(Num[Now+1]==j) Now++;
                f[i][Now]++;
            }
        }
        /*
        for(i=0;i<m;i++,puts(""))
        {
            for(j=0;j<m;j++) W(f[i][j]);
        }
        puts("");
        */
        return;
    }
    int main()
    {
        int i,j,k,ans=0;
        R(n); R(m); R(Mod);
        for(i=1;i<=m;i++)
        {
            char ch=' ';
            while(!isdigit(ch)) ch=getchar();
            Num[i]=ch-'0';
        }
        Pre_f();
        dp[0][0]=1;
        for(i=1;i<=n;i++)
        {
            for(j=0;j<=m-1;j++)
            {
                for(k=0;k<=m-1;k++)
                {
                    Ad(dp[i][j],dp[i-1][k]*f[k][j]%Mod);
                }
            }
        }
        for(i=0;i<m;i++) Ad(ans,dp[n][i]);
        Wl(ans);
        return 0;
    }
    /*
    input
    4 3 100 
    111
    output
    81
    */
    暴力
    #include <bits/stdc++.h>
    using namespace std;
    typedef int ll;
    inline ll read()
    {
        ll s=0;
        bool f=0;
        char ch=' ';
        while(!isdigit(ch))
        {
            f|=(ch=='-'); ch=getchar();
        }
        while(isdigit(ch))
        {
            s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
        }
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0)
        {
            putchar('-'); x=-x;
        }
        if(x<10)
        {
            putchar(x+'0'); return;
        }
        write(x/10);
        putchar((x%10)+'0');
        return;
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) write(x),putchar('
    ')
    const int N=100005,M=25;
    int n,m,Mod;
    int Num[25],f[25][25];
    int ans[25][25],power[25][25],a[25][25],c[25][25];
    inline void Ad(int &x,int y)
    {
        x+=y;
        x-=(x>=Mod)?Mod:0;
        return;
    }
    int Next[25];
    inline void Pre_f()
    {
        int i,j=0;
        Next[1]=0;
        for(i=2;i<=m;i++)
        {
            while((Num[j+1]!=Num[i])&&j) j=Next[j];
            if(Num[j+1]==Num[i]) j++;
            Next[i]=j;
        }
        for(i=0;i<m;i++)
        {
            for(j=0;j<=9;j++)
            {
                int Now=i;
                while((Num[Now+1]!=j)&&Now) Now=Next[Now];
                if(Num[Now+1]==j) Now++;
                f[i][Now]++;
            }
        }
        /*
        for(i=0;i<m;i++,puts(""))
        {
            for(j=0;j<m;j++) W(f[i][j]);
        }
        puts("");
        */
        return;
    }
    int main()
    {
        int i,j,k,Sum=0;
        R(n); R(m); R(Mod);
        for(i=1;i<=m;i++)
        {
            char ch=' ';
            while(!isdigit(ch)) ch=getchar();
            Num[i]=ch-'0';
        }
        Pre_f();
        ans[0][0]=1;
        for(i=0;i<=m-1;i++) power[i][i]=1;
        memmove(a,f,sizeof a);
        while(n)
        {
            if(n&1)
            {
                memset(c,0,sizeof c);
                for(i=0;i<=m-1;i++) for(j=0;j<=m-1;j++) for(k=0;k<=m-1;k++)
                {
                    Ad(c[i][j],power[i][k]*a[k][j]%Mod);
                }
                memmove(power,c,sizeof power);
            }
            memset(c,0,sizeof c);
            for(i=0;i<=m-1;i++) for(j=0;j<=m-1;j++) for(k=0;k<=m-1;k++)
            {
                Ad(c[i][j],a[i][k]*a[k][j]%Mod);
            }
            memmove(a,c,sizeof a);
            n>>=1;
        }
        memset(c,0,sizeof c);
        for(i=0;i<=0;i++) for(j=0;j<=m-1;j++) for(k=0;k<=m-1;k++)
        {
            Ad(c[i][j],ans[i][k]*power[k][j]%Mod);
        }
        memmove(ans,c,sizeof ans);
        for(i=0;i<m;i++) Ad(Sum,ans[0][i]);
        Wl(Sum);
        return 0;
    }
    /*
    input
    4 3 100 
    111
    output
    81
    
    input
    1000000000 19 9973
    1010100110011000001
    output
    5753
    */
    矩阵乘法
  • 相关阅读:
    SMTP协议原始命令码和工作原理[转]
    VC++ SMTP协议电子邮件传送剖析
    C++编译模式(转)
    IE6下select标签覆盖div的完美解决办法
    星级评论插件
    CSS Reset CSS Framework
    if判断IE浏览器的类型
    通过Prototype属性添加Array删除重复数据方法
    Javascript性能优化
    我自己的Javascript 库,封装了一些常用函数
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10507823.html
Copyright © 2011-2022 走看看