码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1009--GT考试(KMP&DP&矩阵乘法)

时间:2017-10-23 12:54:50      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:while   geo   get   using   tor   cpp   pac   ade   str   

    RP++

题目链接:

     http://www.lydsy.com/JudgeOnline/problem.php?id=1009 

Solution

    考虑DP。。。

    dp [ i ] [ j ] 表示现在放完了 i 位,没有出现不吉利数字,但是末尾已经与不吉利数字最多对应了j 位的情况的数量

    状态转移方程。。。说起来很麻烦但很显然

    先对“不吉利数字”做KMP,然后就可以根据此时状态进行DP。。

    但是发现 i 这一维太大了。。。不论时间还是空间都是不允许的。。

    于是要用矩阵乘法加速DP。。。

    具体实现还是直接看代码吧。。。。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define M 1010
#define LL long long
#define mod 1000000007
using namespace std;
int n,m,p;
int nxt[M];
char s[25];
struct jz{
    int x[22][22];
    friend jz operator *(const jz &a,const jz &b){
        jz tmp;
        for(int i=0;i<m;i++)
            for(int j=0;j<m;j++){
                tmp.x[i][j]=0;
                for(int k=0;k<m;k++)
                    tmp.x[i][j]=(tmp.x[i][j]+a.x[i][k]*b.x[k][j])%p;
            }
        return tmp;
    }
}a,b;
void KMP(){
    int f=0;
    for(int i=2;i<=m;i++){
        while(f>0&&s[f+1]!=s[i]) f=nxt[f];
        if(s[f+1]==s[i]) f++;
        nxt[i]=f;
    }
    for(int i=0;i<m;i++)
        for(int j=‘0‘;j<=‘9‘;j++){
            f=i;
            while(f>0&&s[f+1]!=j) f=nxt[f];
            if(s[f+1]==j) b.x[i][f+1]++;
            else b.x[i][0]++;
        }
}
void pow(){
    while(n){
        if(n&1) a=a*b;
        n>>=1;
        b=b*b;
    }
}
int main(){
    int ans=0;
    scanf("%d%d%d",&n,&m,&p);
    scanf("%s",s+1);
    KMP();
    for(int i=0;i<m;i++)
        a.x[i][i]=1;
    pow();
    for(int i=0;i<m;i++)
        ans=(ans+a.x[0][i])%p;
    printf("%d\n",ans);
    return 0;
}

  

  

This passage is made by Iscream-2001.

BZOJ 1009--GT考试(KMP&DP&矩阵乘法)

标签:while   geo   get   using   tor   cpp   pac   ade   str   

原文地址:http://www.cnblogs.com/Yuigahama/p/7714631.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!