P3193 [HNOI2008] GT考试 解题报告
1.数学知识(一)
2.P3193 [HNOI2008] GT考试 解题报告
3.P7976 解题报告4.P10315 解题报告5.P10499 解题报告6.P11130 解题报告7.CF755D 数学规律法 解题报告8.数学知识(二)题目传送门
题目大意:
给定一个长度为
数据范围:
思路:
不难发现和 这道题 很像,只是
朴素 dp 思路在 状态机模型 dp 中写了,这里只讲优化。
朴素做法的时间复杂度为
观察一下状态转移方程:
对于每个
把状态转移方程展开,以
这不就是矩阵乘法的形式吗?
根据上面的分析,我们构造的矩阵
现在的问题变成了如何构造矩阵
根据状态转移方程,若
为什么呢,看这张图就明白了:
其实图是我偷的(
那么矩阵
流程:
先预处理 KMP 的
时间复杂度:
#include <cstring>
#include <iostream>
using namespace std;
const int N = 25;
int n, m, mod;
char s[N];
int ne[N];
struct Matrix {
int mar[N][N];
Matrix() {memset(mar, 0, sizeof mar);}
void init() {
memset(mar, 0, sizeof mar);
for(int i = 0; i < m; i++)
mar[i][i] = 1;
}
Matrix operator *(const Matrix &o) const {
Matrix res;
for(int i = 0; i < m; i++)
for(int j = 0; j < m; j++)
for(int k = 0 ; k < m; k++)
res.mar[i][j] = (res.mar[i][j] + mar[i][k] * o.mar[k][j]) % mod;
return res;
}
}A;
int qpow(int k) {
Matrix res;
res.mar[0][0] = 1;
while(k) {
if(k & 1) res = res * A;
A = A * A;
k >>= 1;
}
int ans = 0;
for(int i = 0; i < m; i++)
ans = (ans + res.mar[0][i]) % mod;
return ans;
}
int main() {
scanf("%d%d%d%s", &n, &m, &mod, s + 1);
for(int i = 2, j = 0; i <= m; i++) {
while(j && s[j + 1] != s[i]) j = ne[j];
if(s[j + 1] == s[i]) j++;
ne[i] = j;
}
for(int j = 0; j < m; j++)
for(int k = '0'; k <= '9'; k++) {
int p = j;
while(p && s[p + 1] != k) p = ne[p];
if(s[p + 1] == k) p++;
if(p < m) A.mar[j][p]++;
}
printf("%d\n", qpow(n));
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!