题目大意:用k种字符构建两个长度为n的字符串(每种字符有无限多个),要求对应位置字符相同的连续子串最长长度为m,问方法数。

其中k,n,m是输入,n(1<=n<=1000000000), m(1<=m<=10), k(1<=k<=26).

对题目解释更详细点儿,如下两串

123456

223466

这个的“对应位置字符相同的连续子串最长长度”是3,是字符串“234”。

解题思路,这题一看就是DP或者组合数学,但是不会组合数学,只能DP了
dp[i][j]表示前i个字符,最后j个位置相同的方法数

第三维01表示该状态是否包含了至少一个长度为m的“对应位置相同子串”

dp[i][j][0]=dp[i-1][j-1][0]*k                                                          (0<j<m)
dp[i][0][0]=sum(dp[i-1][0到m-1][0])*k*(k-1)
dp[i][j][1]=dp[i-1][j-1][1]*k                                                          (0<j<=m)
dp[i][0][1]=(sum(dp[i-1][0到m][1])+dp[i-1][m-1][0])*k*(k-1)
 
由于第一维范围过大,且只和前一个状态有关,很明显想到矩阵乘法优化递推。完整代码如下:
 #include <iostream>
#include <cstdio>
#include <cstring> using namespace std;
typedef long long ll;
const int N = ;
const ll MOD=;
struct Mat {
ll mat[N][N];
Mat()
{
memset(mat,,sizeof(mat));
}
void clear(){
memset(mat,,sizeof(mat));
}
}; ll num[N];
int n, m,K;
Mat a; void init() {
//初始化状态转移矩阵
a.clear();
for(int j=;j<m;j++)a.mat[][j]=K*(K-);
for(int i=;i<m;i++)a.mat[i][i-]=K;
for(int j=m;j<=*m;j++)a.mat[m][j]=K*(K-);
for(int i=m+;i<=*m;i++)a.mat[i][i-]=K;
a.mat[*m][m-]=K;
} Mat operator * (Mat a, Mat b) {
Mat c;
for(int i=;i<=*m;i++){
for(int j=;j<=*m;j++){
for(int k=;k<=*m;k++){
c.mat[i][j]+=b.mat[i][k]*a.mat[k][j];
c.mat[i][j]%=MOD;
}
}
}
return c;
} Mat operator ^ (Mat a, int k) {
//初状态
Mat c;
c.mat[][]=;
//快速幂
for(; k; k >>= ) {
if(k&) c = c*a;
a = a*a;
}
return c;
} int main() {
//freopen("data.in", "r", stdin);
int T;
scanf("%d",&T);
while(~scanf("%d%d%d",&n,&m,&K)) {
//初始化状态转移矩阵
init();
//矩阵快速幂,初始左矩阵不是单位矩阵,是初状态
a = a^n;
//得到最终矩阵后求答案
ll ans=;
for(int i = m; i <= *m; ++i) {
ans+=a.mat[i][];
ans%=MOD;
}
printf("%lld\n", ans);
}
return ;
}

HDU 5863

然后写这个主要是想记录下矩阵乘法的板子

#include <iostream>
#include <cstdio>
#include <cstring> using namespace std;
typedef long long ll;
const int N = ;
const long long MOD=;
struct Mat {
ll mat[N][N];
Mat()
{
memset(mat,,sizeof(mat));
}
void clear(){
memset(mat,,sizeof(mat));
}
}; ll num[N];
int n, m,K;
Mat a; void init() {
//初始化状态转移矩阵
a.clear();
for(int j=;j<m;j++)a.mat[][j]=K*(K-);
for(int i=;i<m;i++)a.mat[i][i-]=K;
for(int j=m;j<=*m;j++)a.mat[m][j]=K*(K-);
for(int i=m+;i<=*m;i++)a.mat[i][i-]=K;
a.mat[*m][m-]=K;
} Mat operator * (Mat a, Mat b) {
Mat c;
for(int i=;i<=*m;i++){
for(int j=;j<=*m;j++){
for(int k=;k<=*m;k++){
c.mat[i][j]+=b.mat[i][k]*a.mat[k][j];
c.mat[i][j]%=MOD;
}
}
}
return c;
} Mat operator ^ (Mat a, int k) {
//初状态
Mat c;
c.mat[][]=;
//快速幂
for(;k;k>>=){
if(k&)c=c*a;
a=a*a;
}
return c;
} int main() {
//freopen("data.in", "r", stdin);
//初始化状态转移矩阵
init();
//矩阵快速幂,初始左矩阵不是单位矩阵,是初状态
a = a^n;
return ;
}
 
 

HDU 5863 cjj's string game (矩阵乘法优化递推)的更多相关文章

  1. HDU 5863 cjj's string game ( 16年多校10 G 题、矩阵快速幂优化线性递推DP )

    题目链接 题意 : 有种不同的字符,每种字符有无限个,要求用这k种字符构造两个长度为n的字符串a和b,使得a串和b串的最长公共部分长度恰为m,问方案数 分析 : 直觉是DP 不过当时看到 n 很大.但 ...

  2. HDU 5863 cjj's string game

    $dp$,矩阵加速. 设$dp[i][j][0]$表示:长度为$i$的两个字符串,之前还未出现过长度为$m$相同的,目前为止最后$j$个是相同的. 设$dp[i][j][1]$表示:长度为$i$的两个 ...

  3. [模板][题解][Luogu1939]矩阵乘法加速递推(详解)

    题目传送门 题目大意:计算数列a的第n项,其中: \[a[1] = a[2] = a[3] = 1\] \[a[i] = a[i-3] + a[i - 1]\] \[(n ≤ 2 \times 10^ ...

  4. BZOJ 4870: [Shoi2017]组合数问题 矩阵乘法_递推

    Code: #include <cstdio> #include <cstring> #include <algorithm> #define setIO(s) f ...

  5. [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

    题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...

  6. [转]OpenBLAS项目与矩阵乘法优化

    课程内容 OpenBLAS项目介绍 矩阵乘法优化算法 一步步调优实现 以下为公开课完整视频,共64分钟: 以下为公开课内容的文字及 PPT 整理. 雷锋网的朋友们大家好,我是张先轶,今天主要介绍一下我 ...

  7. 【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化

    挺好的数位dp……先说一下我个人的做法:经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数 f[i]:所有数 ...

  8. bzoj4870: [Shoi2017]组合数问题(DP+矩阵乘法优化)

    为了1A我居然写了个暴力对拍... 那个式子本质上是求nk个数里选j个数,且j%k==r的方案数. 所以把组合数的递推式写出来f[i][j]=f[i-1][j]+f[i-1][(j-1+k)%k].. ...

  9. 形态形成场(矩阵乘法优化dp)

    形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 ...

随机推荐

  1. node.js date-utils

    前端引用 <script type="text/javascript" src="date-utils.min.js"></script> ...

  2. 如何在在页面中清除一个已知的cookie?

    前些天在写一个项目的时候,使用cookie来存储一些用户数据,在用户登出时需要清理以往的数据,对于一个初学者来说,我需要学习如何清除一个已知的cookie. 首先,引入两个js文件: 1.jquery ...

  3. 文档控件NTKO OFFICE 详细使用说明之预览Excel文件(查看、编辑、保存回服务器)

    1.在线预览Excel文件 (1) 运行环境 ① 浏览器:支持IE7-IE11(平台版本还支持Chrome和Firefox) ② IE工具栏-Internet 选项:将www.ntko.com加入到浏 ...

  4. 12) 十分钟学会android--APP通信传递消息之简单数据传输

    程序间可以互相通信是Android程序中最棒的功能之一.当一个功能已存在于其他app中,且并不是本程序的核心功能时,完全没有必要重新对其进行编写. 本章节会讲述一些通在不同程序之间通过使用Intent ...

  5. 揭秘IPHONE X刷脸认证的技术奥秘

    苹果最新发布的Iphone X具有一个全新的功能叫做刷脸认证,背后的技术其实是生物密码的更新,通过人脸识别取代了传统的指纹识别,大家肯定对这种新技术非常感兴趣,下面我们通过这篇文章为大家介绍人脸识别的 ...

  6. c++常用功能封装

    C++文件读写的封装 在C++开发中,文件读写是很常用的功能,出于代码复用的考虑,将它们进行封装. 其中,默认读写的文件是文本文件,并且需要按行处理.调用者只需要关注读取出来的每一行的处理方式.写文件 ...

  7. sass揭秘之@if,@for,@each(转载)

    因为文章内含有很多sass代码,如需自己动手查看编译结果,推荐使用sassmeister这款在线编译工具,方便你阅读学习. 经过上两篇揭秘,大家心里对sass应该有了很好的认知感了,这篇文章基于前面两 ...

  8. JS 封装一个求n~m的求和函数

    var a = 0;    cc(2,10);    function cc(n,m){        for(var i =n;i<(m+1);i++){            a = a + ...

  9. BZOJ 1266: [AHOI2006]上学路线route Floyd_最小割

    十分简单的一道题. 图这么小,跑一边 Floyd 就得到第一问最短路径的答案. 考虑第二问怎么求:我们可以先将最短路径组成的图从原图中抽离出来,构成新图 $G$. 我们发现,只要 $G$ 的起点与终点 ...

  10. js将timestamp对象与时间字符串之间的转换

    1. 时间戳转日期字符串 var timestamp = timestampObj.time;获取时间戳的毫秒数 var d = new Date(timestamp); //根据时间戳生成的时间对象 ...