题目链接

题意 : 有种不同的字符,每种字符有无限个,要求用这k种字符构造两个长度为n的字符串a和b,使得a串和b串的最长公共部分长度恰为m,问方案数

分析 :

直觉是DP

不过当时看到 n 很大、但是 m 很小的时候

发现此题DP并不合适、于是想可能是某种组合数学的问题可以直接公式算

看到题解的我、恍然大悟、对于这种数据、可以考虑一下矩阵快速幂优化的DP

首先要想到线性递推的 DP 式子

最直观的想法就是 dp[i][j] = 到第 i 个位置为止、前面最长匹配长度为 j 的方案数

但是如果仔细想想、这样子的定义状态并不好转移、遂换一种思路

定义 dp[i][j] = 到第 i 个位置为止、以第 i 个字符为结尾的匹配串的长度为 j 的方案数

有转移

dp[i][0] = (dp[i-1][0] + dp[i-1][1] + .... + dp[i-1][m] ) * k * (k-1)   (k * (k-1) 的意义是a、b串第 i 个字符不一样的方案数)

dp[i][j] = dp[i-1][j-1] * k ( j ≤ i )

然后尝试去构造矩阵、此处引用 链接

但是注意一下这里的 DP 意义、答案最后并不是 dp[n][m]

dp[n][0] + dp[n][1] + ... + dp[n][m] 可以看成到第 n 个位置为止匹配长度 ≤ m 的方案数

那么如果可以得到匹配长度 ≤ m-1 的方案数两者相减就可以得到匹配长度恰为 m 的方案数了

所以做两次矩阵快速幂即可

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;const int maxn = 1e5 + 10;
const LL mod = 1e9 + 7;struct MAT{LL val[12][12];int sz;MAT(){};MAT(int _sz){ sz = _sz; memset(val, 0, sizeof(val)); }friend MAT operator * (const MAT & A, const MAT & B){MAT C(A.sz);for(int k = 1; k <= C.sz; k++)for(int i = 1; i <= C.sz; i++){if(A.val[i][k] == 0) continue;for(int j = 1; j <= C.sz; j++){C.val[i][j] = C.val[i][j] + A.val[i][k] * B.val[k][j] % mod;if(C.val[i][j] >= mod) C.val[i][j] -= mod;}}return C;}
};MAT pow_mod(MAT a, LL b)
{MAT ret(a.sz);for(int i=1; i<=ret.sz; i++) ret.val[i][i] = 1;while(b){if(b & 1) ret = ret * a;a = a * a;b >>= 1;}return ret;
}LL Cal(int n, int m, int k)
{MAT A(m+1);for(int i=1; i<=A.sz; i++) A.val[1][i] = 1LL * k * (k - 1);for(int i=2; i<=A.sz; i++) A.val[i][i-1] = k * 1LL;A = pow_mod(A, n);LL ret = 0;for(int i=1; i<=A.sz; i++)ret = (ret + A.val[i][1]) % mod;return ret;
}int main(void){__stTIME();__IOPUT();int nCase;sci(nCase);while(nCase--){int n, m, k;sciii(n, m, k);printf("%lld\n", (Cal(n, m, k) - Cal(n, m-1, k) + mod) % mod);}__enTIME();return 0;}void __stTIME()
{#if _TIMESTART = clock();#endif
}void __enTIME()
{#if _TIMEEND = clock();cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;#endif
}void __IOPUT()
{#if _INPUTfreopen("in.txt", "r", stdin);#endif#if _OUTPUTfreopen("out.txt", "w", stdout);#endif
}

View Code

转载于:https://www.cnblogs.com/LiHior/p/9797051.html

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

  1. Recursive sequence HDU - 5950 (递推 矩阵快速幂优化)

    题目链接 F[1] = a, F[2] = b, F[i] = 2 * F[i-2] + F[i-1] + i ^ 4, (i >= 3) 现在要求F[N] 类似于斐波那契数列的递推式子吧, 但 ...

  2. HDU 6185 Covering 矩阵快速幂 递推

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6185 题目描述: 一个4*n的矩形, 你用1*2的矩形覆盖有多少种方案, n <= 1e18 ...

  3. hdu 6395Sequence【矩阵快速幂】【分块】

    Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total ...

  4. HDU5863 cjj's string game(DP + 矩阵快速幂)

    题目 Source http://acm.split.hdu.edu.cn/showproblem.php?pid=5863 Description cjj has k kinds of charac ...

  5. HDU 1757 A Simple Math Problem(矩阵快速幂)

    题目链接 题意 :给你m和k, 让你求f(k)%m.如果k<10,f(k) = k,否则 f(k) = a0 * f(k-1) + a1 * f(k-2) + a2 * f(k-3) + -- ...

  6. HDU 2276 Kiki Little Kiki 2 (位运算+矩阵快速幂)

    HDU 2276 Kiki & Little Kiki 2 (位运算+矩阵快速幂) ACM 题目地址:HDU 2276 Kiki & Little Kiki 2 题意:  一排灯,开关 ...

  7. HDU 2243考研路茫茫——单词情结 (AC自动机+矩阵快速幂)

    背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...

  8. hdu 5451 Best Solver 矩阵循环群+矩阵快速幂

    http://acm.hdu.edu.cn/showproblem.php?pid=5451 题意:给定x    求解 思路: 由斐波那契数列的两种表示方法, 之后可以转化为 线性表示 F[n] = ...

  9. 湖南大学第十四届ACM程序设计新生杯(重现赛)L-The Digits String (矩阵快速幂)

    题目链接 题目描述 Consider digits strings with length n, how many different strings have the sum of digits a ...

最新文章

  1. 华表 单元格公式设定与计算
  2. 作业09-集合与泛型
  3. Caffe中merge卷积和bn层的原理
  4. adb连接MuMu、逍遥、夜神、雷电模拟器以及腾讯手游助手以及断开连接
  5. 畅捷通(chanjet)T1各版本
  6. Textbox的用法
  7. JavaScript判断数组是否包含某元素
  8. WinForm中用C#实现左侧导航菜单(1)——概览
  9. [网络安全提高篇] 一一六.恶意代码同源分析及BinDiff软件基础用法
  10. ppspp android编译,PPSSPP模拟器通用设置,伪福利
  11. 笔记本电脑设置自动关机以及取消自动关机
  12. 第七届ArcGIS暨ERDAS用户大会
  13. java时间差的百分之二十,java计算时间差及某个时间段数据
  14. 顶级科学家是哲学家,顶级investor是哲学家
  15. transporter上传卡正在交付_Xcode11或Transporter上传app store 一直卡在Authenticating with the App Store 的解决...
  16. mysql错误码为1045_mysql错误代码1045的原因及解决方案
  17. 朗读评价语言集锦_朗读点评评语
  18. 基于C#面向对象的特性搭建游戏框架
  19. 联合CSDN官方建设新社区,奖励多多,任务简单
  20. 【渝粤教育】电大中专药理学基础_1作业 题库

热门文章

  1. Maven Oracle JDBC
  2. putty远程登录linux无ssh,收集的linux远程ssh连接putty失败解决办法!
  3. Ubuntu系统(四)-修改主机名和配置DNS上网
  4. java 下一代_Java 下一代: 混入和特征
  5. WorkFlow入门Step.3—Adding Procedural Elements-For...
  6. “小程序”的最佳入口位置--关于微信小程序的思考笔记
  7. 计算机组组内培训记录,计算机教研组活动记录
  8. android的命令行使用,Android命令行启动程序正确使用技巧解析
  9. AIR:使用 HTML + Javascript 开发桌面应用
  10. Xamarin For Android 打包编译APK文件详细图文教程