Sam's Numbers 矩阵快速幂优化dp
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的更多相关文章
- 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 ...
- 省选模拟赛 Problem 3. count (矩阵快速幂优化DP)
Discription DarrellDarrellDarrell 在思考一道计算题. 给你一个尺寸为 1×N1 × N1×N 的长条,你可以在上面切很多刀,要求竖直地切并且且完后每块的长度都是整数. ...
- 2018.10.22 bzoj1009: [HNOI2008]GT考试(kmp+矩阵快速幂优化dp)
传送门 f[i][j]f[i][j]f[i][j]表示从状态"匹配了前i位"转移到"匹配了前j位"的方案数. 这个东西单次是可以通过跳kmp的fail数组得到的 ...
- 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个 ...
- 【bzoj1009】[HNOI2008]GT考试(矩阵快速幂优化dp+kmp)
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 这道题一看数据范围:$ n<=10^9 $,显然不是数学题就是矩乘快速幂优 ...
- LOJ2325. 「清华集训 2017」小 Y 和恐怖的奴隶主【矩阵快速幂优化DP】【倍增优化】
LINK 思路 首先是考虑怎么设计dp的状态 发现奴隶主的顺序没有影响,只有生命和个数有影响,所以就可以把每个生命值的奴隶主有多少压缩成状态就可以了 然后发现无论是什么时候一个状态到另一个状态的转移都 ...
- bzoj1009 [HNOI2008]GT考试——KMP+矩阵快速幂优化DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 字符串计数DP问题啊...连题解都看了好多好久才明白,别提自己想出来的蒟蒻我... 首 ...
- 2019.02.11 bzoj4818: [Sdoi2017]序列计数(矩阵快速幂优化dp)
传送门 题意简述:问有多少长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数,且其中至少有一个数是质数,答案对201704082017040820170408取模(n≤1e9, ...
- 2018.10.19 NOIP模拟 硬币(矩阵快速幂优化dp)
传送门 不得不说神仙出题人DZYODZYODZYO出的题是真的妙. f[i][j][k]f[i][j][k]f[i][j][k]表示选的硬币最大面值为iii最小面值不小于jjj,总面值为kkk时的选法 ...
随机推荐
- 一个关于前端页面的小标签<tbody>
我们有时候希望将表格的内容分为多个模块,这时候就可以使用<tbody>标签,它是<table>的字标签,是<tr>的父标签,可以使用它达到一种设置样式的结果.
- (转)HLS协议,html5视频直播一站式扫盲
本文来自于腾讯bugly开发者社区,原文地址:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1277 视频直播这么火,再不学就 ou ...
- C++中两个类相互包含引用问题
在构造自己的类时,有可能会碰到两个类之间的相互引用问题,例如:定义了类A类B,A中使用了B定义的类型,B中也使用了A定义的类型 class A { int i; B b; } class B { in ...
- 集训Day9
又是不想学化学但元气满满的一天呢qwq 今天又有新的故事发生那就是! bzoj2150 最小流 每个点拆成$a_x$和$a_y$ $S$->$a_x$容量为1 $a_y$->$T$容量为1 ...
- java-02 for循环,while循环
###############获取一个数字的每位数字############### #############1-100奇数和偶数和############## public class Sum { ...
- 「LOJ#10042」「一本通 2.1 练习 8」收集雪花 (map
题目描述 不同的雪花往往有不同的形状.在北方的同学想将雪花收集起来,作为礼物送给在南方的同学们.一共有 n 个时刻,给出每个时刻下落雪花的形状,用不同的整数表示不同的形状.在收集的过程中,同学们不希望 ...
- maven学习八 关于maven的version
在一个有继承关系的POM文件中,父项目中有如下定义: <dependencyManagement> <dependency> <groupId>com.type ...
- Linux 切换字符界面和图形界面
1. 切换方式 # root 权限 systemctl get-default # 获取当前模式 systemctl set-default graphical.target # 设置开机为图形界面 ...
- git for eclipse 如何取消误操作的忽略(ignore)操作
直接删除ignore文件即可.如下显示: 原文引用:https://blog.csdn.net/exceptionss/article/details/79082601
- netstat -st输出解析(二)
转自:http://perthcharles.github.io/2015/11/10/wiki-netstat-proc/ netstat -st输出的两个重要信息来源分别是/proc/net/sn ...