题目大意:用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. Nginx 404 500

    Nginx反向代理自定义404错误页面 http中添加 proxy_intercept_errors on; server中添加 error_page 404 = https://www.longda ...

  2. 第六课: - GroupBy函数

    第 6 课   让我们看一看 groupby 函数. In [1]: # Import libraries import pandas as pd import sys In [2]: print(' ...

  3. javascript一个作用域案例分析

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. angular基础入门

    第一章 AngularJs入门 AngularJS是一款由Google公司开发维护的前端框架,其克服了HTML在构建应用上的诸多不足,从而降低了开发成本提升了开发效率. 1 特点 AngularJS与 ...

  5. Spring学习笔记之基础、IOC、DI(1)

    0.0 Spring基本特性 Spring是一个开源框架:是基于Core来架构多层JavaEE系统 1.0 IOC 控制反转:把对象的创建过程交给spring容器来做. 1.1 application ...

  6. java中参数传递实例

    //在函数中传递基本数据类型,            2. public class Test {         4.     public static void change(int i, in ...

  7. 【Oracle】手工建库启动到nomount状态时错误ORA-09925,ORA-01017

    配置好pfile和口令文件后启动数据库到nomount状态下出现错误: [oracle@localhost ~]$ sqlplus / as sysdba SQL*Plus: Release 11.2 ...

  8. UML+模式设计概述

    转自于:http://blog.csdn.net/rexuefengye/article/details/13020225 工程学:工程庞大到一定程度必须是用工程学方法,好比直接用水泥沙子建设实用的摩 ...

  9. Rx (Reactive Extensions)介绍

    Reactive Extensions (Rx) 原来是由微软提出的一个综合了异步和基于事件驱动编程的库包,使用可观察序列和LINQ-style查询操作. 使用Rx, 开发者可以用Observable ...

  10. Kafka学习笔记(4)----Kafka的Leader Election

    1. Zookeeper的基本操作 zookeeper中的节点可以持久化/有序的两个维度分为四种类型: PERSIST:持久化无序(保存在磁盘中) PERSIST_SEQUENTIAL:持久化有序递增 ...