【题解】HNOI2008GT考试

这题好难啊……完全不懂矩阵加速递推的我TAT

这道题目要求我们求出不含不吉利数字的字符串总数,那么我们有dp方程 : dp[i][j](长度为 i 的字符串,最长与不吉利数字前缀相同的后缀长度为 j 的方案数)。 dp[i][j] = Σdp[i - 1][k] * a[k][j] (a 数组表示从 k 状态转移到 j 状态的方案数)。a 数组我们可以通过 kmp 对不吉利数字的每一个前缀后面加上‘0’~‘9’转移匹配得到(匹配成功表示成功转移状态,a[k][j]++;否则表示此时没有重合的后缀,a[k][0]++)。

此时这道题目我们已经拥有了一个相对优的解法了,但是还不够。注意到上面的式子,我们对于dp数组与a数组分别建立矩阵,dp矩阵是一个列矩阵,一列代表1~k的状态,a矩阵第 j 行上每个数分别表示a[j][k]。所以得到的答案dp[i][j]即为dp矩阵与a矩阵第 j 行的乘积。矩阵快速幂优化即可。

#include <bits/stdc++.h>
using namespace std;
#define maxn 100000
int n, m, Mod, k, ans;
char s[maxn], nxt[maxn];

int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) k = -1; c = getchar(); }
    while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar();
    return x * k;
}

struct Matrix
{
    int num[52][52];
    void init()
    {
        memset(num, 0, sizeof(num));
    }
    Matrix operator*(const Matrix &x)
    {
        Matrix tem;
        tem.init();
        for(int i = 0; i < m; i ++)
            for(int j = 0; j < m; j ++)
                for(int k = 0; k < m; k ++)
                {
                    tem.num[i][j] += (num[i][k] * x.num[k][j]) % Mod;
                    tem.num[i][j] %= Mod;
                }
        return tem;
    }
}T, S;

void KMP()
{
    int j = 0;
    for(int i = 2; i <= m; i ++)
    {
        while(j && s[j + 1] != s[i]) j = nxt[j];
        if(s[j + 1] == s[i]) j ++;
        nxt[i] = j;
    }
    j = 0;
    for(int i = 0; i < m; i ++)
        for(int k = 0; k <= 9; k ++)
        {
            j = i;
            while(j && s[j + 1] != (char) k + ‘0‘) j = nxt[j];
            if(s[j + 1] == (char) k + ‘0‘) T.num[i][j + 1] ++;
            else T.num[i][0] ++;
        }
}

void Qpow()
{
    for(int i = 0; i < m; i ++) S.num[i][i] = 1;
    while(n)
    {
        if(n & 1) S = S * T;
        T = T * T;
        n >>= 1;
    }
}

int main()
{
    n = read(), m = read(), k = read();
    Mod = k;
    scanf("%s", s + 1);
    KMP();
    Qpow();
    for(int i = 0; i < m; i ++)
        ans = (ans + S.num[0][i]) % Mod;
    printf("%d\n", ans);
    return 0;
} 

原文地址:https://www.cnblogs.com/twilight-sx/p/8542749.html

时间: 2024-08-30 14:28:46

【题解】HNOI2008GT考试的相关文章

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

第六届蓝桥杯本科B组C++省赛题解

比赛结束已经一星期了,成绩也出来了,江苏非211组的省前十,但是深感自己还是有太多的不足.绝对不能以自己还只是大一为借口,acm这条路还长的很. 目测得了95分(满分150),第一题错了,代码填空第一题错了,倒数第二题扣了一点分,最后一道大题全错. 之所以会这么晚来发这道题解,是因为深感自己不足,倒数第二题之所以没有做出来,是因为自己居然不会用[矩阵快速幂].因此,现学现用以自省. 关于题目:所有填空题都可以纯暴力,只要会回溯剪枝法对于蓝桥杯已经足够了.大题目难度一年比一年高 第一题 结果填空

6.11 考试修改+总结

第三题至今没敢写,感觉好恐怖QAQ 今天考得好糟糕 第一题只写了10分的暴力+(k=1)20分的网络流 后来题解告诉我k>1的时候可以分治到k=1,每层分治解决方法是同k=1的 考试的时候没有注意到2^k这个比较神奇的可以分治的性质 而且自己考场上丝薄了,没有发现因为是二分图可以直接跑欧拉回路的性质,而是裸套网络流模型 第二题其实已经接近想出了题解 自己考试的时候成功证明了暴力的复杂度是线性的 但是没有想到如何寻找0-1对,然后就只能暴力用Splay维护1所在的位置了 默默祈祷数据不要太卡我的做

NIOP 09 题解

2009 NOIP 提高组 题解 这次考试,呃,除了第一题就没怎么拿分.后面几道题都比较难想,想到了又不怎么写的出来,哎. 几道题总的难度都不是很大,总结最近几次做题来说,在图论上只是还是很欠缺,做题都不怎么会去想图论方面的知识,但其实只要能想到用图论知识的话最近的几道题都还是很好处理的.假期要在复习一遍图论了. 这次的题主要是读懂题. T1 潜伏者 T2 Hankson的趣味题 T3 最优贸易 T4 靶形数独 T1 额,该怎么判断怎么判断吧.旁边的cyy同学认为推出25个字母的密码可以自行推出

11.10模拟

得了92.5分.辣鸡.懒惰的我不想去掉红字了,凑合着看吧.  题解:考试的时候想用搜索做,写min函数的时候定义成了bool型,,找了半天错误,咋就是返回1.然后还是可爱的小qg提醒,才知道要处理环. #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<ctime> #define N 10

清北模拟题4

更正:第三组:不存在相同的字符|str|=26,26<=n<=100 题解:kmp+矩阵乘法(类似 GT算法,只需将 GT算法的代码(ps:GT算法是一道题)进行一下修改). #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 10100 #define MAXM 110 #define M 1000000007 using

9.4模拟赛

hao [问题描述] 祖玛是一款曾经风靡全球的游戏,其玩法是:在一条轨道上初始排列着若干个彩色珠子,其中任意三个相邻的珠子不会完全同色.此后,你可以发射珠子到轨道上并加入原有序列中.一旦有三个或更多同色的珠子变成相邻,它们就会立即消失.这类消除现象可能会连锁式发生,其间你将暂时不能发射珠子. 开发商最近准备为玩家写一个游戏过程的回放工具.他们已经在游戏内完成了过程记录的功能,而回放功能的实现则委托你来完成.  游戏过程的记录中,首先是轨道上初始的珠子序列,然后是玩家接下来所做的一系列操作.你的任

2016.10.31.第54套(集训1)

Mushroom的序列[问题描述]Mushroom手中有n个数排成一排,现在Mushroom想取一个连续的子序列,使得这个子序列满足:最多只改变一个数,使得这个连续的子序列是严格上升子序列,Mushroom想知道这个序列的最长长度是多少.[输入格式]第一行一个整数n,表示有n个数.第二行为n个数.[输出格式]一个数,为最长长度.[输入样例]67 2 3 1 5 6[输出样例]5[样例解释]选择第2个数到第6个数,把1改变成4即可.[数据范围]对于30%的数据,n<=10对于60%的数据,n<=

[BZOJ3195][Jxoi2012]奇怪的道路

3195: [Jxoi2012]奇怪的道路 Time Limit: 10 Sec  Memory Limit: 128 MB Description 小宇从历史书上了解到一个古老的文明.这个文明在各个方面高度发达,交通方面也不例外.考古学家已经知道,这个文明在全盛时期有n座城市,编号为1..n.m条道路连接在这些城市之间,每条道路将两个城市连接起来,使得两地的居民可以方便地来往.一对城市之间可能存在多条道路.据史料记载,这个文明的交通网络满足两个奇怪的特征.首先,这个文明崇拜数字K,所以对于任何