zoukankan      html  css  js  c++  java
  • [BZOJ1009][HNOI2008]GT考试

    题目描述

    阿申准备报名参加 GT 考试,准考证号为 NNN 位数 X1,X2…Xn(0≤Xi≤9)X_1,X_2…X_n(0le X_ile9)X1,X2Xn(0Xi9) ,他不希望准考证号上出现不吉利的数字。 他的不吉利数学 A1,A2…Am(0≤Ai≤9)A_1,A_2…A_m(0le A_ile 9)A1,A2Am(0Ai9) 有 MMM 位,不出现是指 X1,X2…XnX_1,X_2…X_nX1,X2Xn 中没有恰好一段等于 A1,A2…AmA_1,A_2…A_mA1​,A2​…Am​ , A1A_1A1​ 和 X1X_1X1​ 可以为 000

    输入输出格式

    输入格式:

    第一行输入N,M,K.接下来一行输入M位的数。

    输出格式:

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

    输入输出样例

    输入样例#1: 
    4 3 100
    111
    输出样例#1: 
    81

    说明

    N≤109,M≤20,K≤1000Nleq10^9,Mleq20,Kleq1000N109,M20,K1000


     

    一脸不可做...

    其实貌似不难我就调了两个小时。。

    设f[i, j]表示填到了第i位,与不吉利数字匹配到第j位的方案总数。

    设g[i, j]表示在第i位后添加一个数字,转移到j的方案数;

    g数组可以用kmp求出,当然暴力也行因为长度太小...其实我暴力调了好长时间换成kmp过了...

    我也不知道为何玄学事情总在我身上发生...

    显然f[i][j] = Σ(i:1~m-1)f[i-1][k] * g[k][j]。

    意思就是f[i][j]是从i-1位加一个数转移过来的。

    n范围1e9,考虑矩阵加速...

    我们的矩阵是个这个样子:

    g[0][0]  g[1][0]  g[2][0]  ...  g[m-2][0]  g[m-1][0]           f[i][0]    f[i+1][0]

    g[0][1]  g[1][1]  g[2][1]  ...  g[m-2][1]  g[m-1][0]           f[i][1]    f[i+1][1]

    ...                        *     ...           =       ...

    ...                      ...        ...

    g[m-1][1]...                  f[i][m-1]   f[i+1][m-1]

    然后快乐地转移...就做完了... 

    吐槽一句:打矩阵好累啊


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    using namespace std;
    inline int read(){
        int res=0;char ch=getchar();
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
        return res; 
    }
    int n, m, mod;
    int g[25][25], nxt[25];
    int str[25];
    int ans;
    
    struct Mat{
        int a[25][25];
        Mat(){memset(a, 0, sizeof a);}
        void init(){for(int i=0;i<25;i++)a[i][i]=1;}
        friend Mat operator * (Mat x, Mat y)
        {
            Mat z;
            for (int k = 0 ; k < 25 ; k ++)
            {
                for (int i = 0 ; i < 25 ; i ++)
                {
                    for (int j = 0 ; j < 25 ; j ++)
                    {
                        z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j]) % mod;
                    }
                }
            }
            return z;
        }
        friend Mat operator ^ (Mat x, int y)
        {
            Mat z;z.init();
            while(y)
            {
                if (y&1) z = z * x;
                x = x * x;
                y >>= 1;
            }
            return z;
        }
    }A, res, B;
    
    int main()
    {
        n = read(), m = read(), mod = read();
        for (int i = 1 ; i <= m ; i ++) scanf("%1d", &str[i]);
        int p = 0;
        for(int i = 2 ; i <= m ; i ++)
        {
            while(p and str[p+1] != str[i])p = nxt[p];
            if(str[p+1]==str[i])p++;
            nxt[i]=p;
        }
        for (int i = 0 ; i < m ; i ++)
        {
            for (int j = 0 ; j <= 9 ; j ++) 
            {
                int k = i;
                while(k and str[k+1] != j) k=nxt[k];
                if (str[k+1] == j) k++;
                if(k != m) g[i][k] ++;
                if (g[i][k] >= mod) g[i][k] -= mod;
            }
        }
        for (int i = 0 ; i <= m - 1 ; i ++)
        {
            for (int j = 0 ; j <= m - 1 ;  j ++)
            {
                A.a[i][j] = g[j][i];
            }
        }
        B.a[0][0] = 1;
        res = A ^ n;
        res = res * B;
        for (int i = 0 ; i <= m - 1 ; i ++) ans = (ans + res.a[i][0]) % mod;
        cout<<ans<<endl;
        return 0;
    } 
  • 相关阅读:
    WIN7远程桌面连接--“发生身份验证错误。要求的函数不受支持”
    django-xadmin使用之更改菜单url
    django-xadmin使用之配置页眉页脚
    django-xadmin定制之列表页searchbar placeholder
    django-xadmin定制之分页显示数量
    Chrome无界面浏览模式与自定义插件加载问题
    Chrome开启无界面浏览模式Python+Windows环境
    django-xadmin中APScheduler的启动初始化
    处理nginx访问日志,筛选时间大于1秒的请求
    将Excel文件转为csv文件的python脚本
  • 原文地址:https://www.cnblogs.com/BriMon/p/9365148.html
Copyright © 2011-2022 走看看