https://www.hackerrank.com/contests/hourrank-21/challenges/sams-numbers

设dp[s][i]表示产生的总和是s的时候,结尾符是i的所有合法方案数。

那么dp[s][i]可以由dp[s - i][1---m]中,abs(i - k) <= d的递推过来。

但是s很大,不能这样解决。

考虑到m只有10,而且dp[s][1]只能由dp[s - 1][1...m]递推过来。

那么先预处理dp[1--m][1--m]

写成m * m的一行(离散化一下就好)

写成dp[1][1]、dp[1][2].....dp[1][m]、、dp[2][1]、dp[2][2].....dp[2][m]、、dp[3][1]、dp[3][2]......dp[3][m]这样

那么dp[1][1]要递推变成dp[2][1],可以构造一个矩阵出来就好了。前m * m - m个可以由后面的得到。

构造矩阵难得就是dp[m][k]要递推到dp[m + 1][k],模拟一下就能找到递推式。主要是知道m比较小,可以暴力离散化来搞。

复杂度1e6 * logs

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = + ;
struct Matrix {
LL a[maxn][maxn];
int row;
int col;
}ans, base;
//struct Matrix matrix_mul(struct Matrix a, struct Matrix b, int MOD) { //求解矩阵a*b%MOD
// struct Matrix c = {0};
// c.row = a.row;
// c.col = b.col;
// for (int i = 1; i <= a.row; i++) {
// for (int j = 1; j <= b.col; j++) {
// for (int k = 1; k <= b.row; k++) {
// c.a[i][j] += a.a[i][k] * b.a[k][j];
// c.a[i][j] = (c.a[i][j] + MOD) % MOD;
// }
// }
// }
// return c;
//} struct Matrix matrix_mul(struct Matrix a, struct Matrix b, int MOD) {
struct Matrix c = {};
c.row = a.row;
c.col = b.col;
for (int i = ; i <= a.row; ++i) {
for (int k = ; k <= a.col; ++k) {
if (a.a[i][k]) {
for (int j = ; j <= b.col; ++j) {
c.a[i][j] += a.a[i][k] * b.a[k][j];
c.a[i][j] = (c.a[i][j] + MOD) % MOD;
}
}
}
}
return c;
}
struct Matrix quick_matrix_pow(struct Matrix ans, struct Matrix base, LL n, int MOD) {
while (n) {
if (n & ) {
ans = matrix_mul(ans, base, MOD);
}
n >>= ;
base = matrix_mul(base, base, MOD);
}
return ans;
}
const int MOD = 1e9 + ;
void add(int &x, int y) {
x += y;
if (x >= MOD) x -= MOD;
}
int dp[][];
LL s, m, d;
int getId(int x, int y) {
return (x - ) * m + y;
}
int res[maxn];
void work() {
cin >> s >> m >> d;
for (int i = ; i <= m; ++i) dp[i][i] = ;
for (int i = ; i <= m; ++i) {
for (int j = ; j <= m && j <= i; ++j) {
for (int k = ; k <= m; ++k) {
if (abs(k - j) > d) continue;
add(dp[i][j], dp[i - j][k]);
}
}
}
if (s <= m) {
int ans = ;
for (int i = ; i <= m; ++i) {
add(ans, dp[s][i]);
}
cout << ans << endl;
return;
}
for (int i = ; i <= m; ++i) {
for (int j = ; j <= m; ++j) {
res[getId(i, j)] = dp[i][j];
}
}
base.col = base.row = m * m;
int to = m + ;
for (int i = ; i <= m * m - m; ++i) {
base.a[to][i] = ;
to ++;
}
int now = ;
for (int i = m * m - m + ; i <= m * m; ++i) {
// int id = getId(m - now + 1, now);
for (int j = ; j <= m; ++j) {
if (abs(j - now) > d) continue;
base.a[getId(m - now + , j)][i] = ;
}
now++;
}
ans.row = , ans.col = m * m;
to = ;
for (int i = ; i <= m; ++i) {
for (int j = ; j <= m; ++j) {
ans.a[][to] = dp[i][j];
to++;
}
}
//
// for (int i = 1; i <= m * m; ++i) {
// for (int j = 1; j <= m * m; ++j) {
// cout << base.a[i][j] << " ";
// }
// cout << endl;
// }
// cout << endl;
// for (int i = 1; i <= m * m; ++i) {
// cout << ans.a[1][i] << " ";
// }
// cout << endl;
ans = quick_matrix_pow(ans, base, s - m, MOD);
int out = ;
for (int i = m * m - m + ; i <= m * m; ++i) {
add(out, ans.a[][i]);
}
// for (int i = 1; i <= m * m; ++i) {
// cout << ans.a[1][i] << " ";
// }
// cout << endl;
cout << out << endl;
}
int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
IOS;
work();
return ;
}

Sam's Numbers 矩阵快速幂优化dp的更多相关文章

  1. 2018.10.23 bzoj1297: [SCOI2009]迷路(矩阵快速幂优化dp)

    传送门 矩阵快速幂优化dp简单题. 考虑状态转移方程: f[time][u]=∑f[time−1][v]f[time][u]=\sum f[time-1][v]f[time][u]=∑f[time−1 ...

  2. 省选模拟赛 Problem 3. count (矩阵快速幂优化DP)

    Discription DarrellDarrellDarrell 在思考一道计算题. 给你一个尺寸为 1×N1 × N1×N 的长条,你可以在上面切很多刀,要求竖直地切并且且完后每块的长度都是整数. ...

  3. 2018.10.22 bzoj1009: [HNOI2008]GT考试(kmp+矩阵快速幂优化dp)

    传送门 f[i][j]f[i][j]f[i][j]表示从状态"匹配了前i位"转移到"匹配了前j位"的方案数. 这个东西单次是可以通过跳kmp的fail数组得到的 ...

  4. 2018.10.16 uoj#340. 【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂优化dp)

    传送门 一道不错的矩阵快速幂优化dpdpdp. 设f[i][j][k][l]f[i][j][k][l]f[i][j][k][l]表示前iii轮第iii轮还有jjj个一滴血的,kkk个两滴血的,lll个 ...

  5. 【bzoj1009】[HNOI2008]GT考试(矩阵快速幂优化dp+kmp)

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 这道题一看数据范围:$ n<=10^9 $,显然不是数学题就是矩乘快速幂优 ...

  6. LOJ2325. 「清华集训 2017」小 Y 和恐怖的奴隶主【矩阵快速幂优化DP】【倍增优化】

    LINK 思路 首先是考虑怎么设计dp的状态 发现奴隶主的顺序没有影响,只有生命和个数有影响,所以就可以把每个生命值的奴隶主有多少压缩成状态就可以了 然后发现无论是什么时候一个状态到另一个状态的转移都 ...

  7. bzoj1009 [HNOI2008]GT考试——KMP+矩阵快速幂优化DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 字符串计数DP问题啊...连题解都看了好多好久才明白,别提自己想出来的蒟蒻我... 首 ...

  8. 2019.02.11 bzoj4818: [Sdoi2017]序列计数(矩阵快速幂优化dp)

    传送门 题意简述:问有多少长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数,且其中至少有一个数是质数,答案对201704082017040820170408取模(n≤1e9, ...

  9. 2018.10.19 NOIP模拟 硬币(矩阵快速幂优化dp)

    传送门 不得不说神仙出题人DZYODZYODZYO出的题是真的妙. f[i][j][k]f[i][j][k]f[i][j][k]表示选的硬币最大面值为iii最小面值不小于jjj,总面值为kkk时的选法 ...

随机推荐

  1. 基于 bi-LSTM和CRF的中文命名实体识别

    follow: https://github.com/zjy-ucas/ChineseNER  这里边主要识别的实体如图所示,其实也就主要识别人名PER,机构ORG和地点LOC: B表示开始的字节,I ...

  2. sed 中带变量的情况

    #teststr="IBM" #sed -n '/' "$teststr" '/=' testfile.txt 在sed中使用变量 通常,我们使用sed进行变量 ...

  3. cmder的下载和使用

    下载地址:http://cmder.net/ 设置环境变量,CMDER_HOME=cmder.exe所在目录,并在path中增加%CMDER_HOME%. 右击我的电脑->属性->(左侧) ...

  4. 关于Tensorflow 加载和使用多个模型的方式

    在Tensorflow中,所有操作对象都包装到相应的Session中的,所以想要使用不同的模型就需要将这些模型加载到不同的Session中并在使用的时候申明是哪个Session,从而避免由于Sessi ...

  5. mysql错误-修改mysql.sock位置

    在Mysql下有时候会出现mysql.sock位置错误,导致无法链接数据库. mac下报错的时候: 首先修改my.cnf 位置在/etc/my.cnf下,假如没有的话,去/usr/locate/mys ...

  6. Visual Studio 编译后去掉只读属性

    Visual Studio 编译后去掉只读属性 attrib $(TargetPath) -R attrib $(TargetDir)$(TargetName).pdb -R

  7. 《TCP/IP详解卷一:协议》 概述

    分层           TCP/IP协议族是一组不同层次上的多个协议的组合.TCP/IP通常被认为是一个四层次协议系统.   链路层(数据链路层或网络接口层):通常包括操作系统中的设备驱动程序和计算 ...

  8. 在python 3.6的eclipse中,导入from lxml import etree老是提示,Unresolved import:etree的错误

    支持代码运行没问题,暂时没有找到真正解决办法,只能通过一下办法暂时解决.如下图:

  9. Java对象序列化详解

    深入理解Java对象序列化 1. 什么是Java对象序列化 Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比 ...

  10. JDK5特性

    静态导入(了解) JDK 1.5 增加的静态导入语法用于导入类的某个静态属性或方法.使用静态导入可以简化程序对类静态属性和方法的调用. 语法: import static 包名.类名.静态属性|静态方 ...