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时的选法 ...
随机推荐
- Seq2SQL :使用强化学习通过自然语言生成SQL
论文: https://einstein.ai/static/images/layouts/research/seq2sql/seq2sql.pdf 数据集:https://github.com/s ...
- k8s-flannel容器集群网络部署
[root@k8s-master src]# wget https://github.com/coreos/flannel/releases/download/v0.9.1/flannel-v0.9. ...
- Confd 配置指导
Quick Start Guide Before we begin be sure to download and install confd. Select a backend confd supp ...
- bzoj 3771: Triple 快速傅里叶变换 FFT
题目大意: 给出\(n\)个互不相同的物品,每个物品有价值\(x_i(x_i \leq 40000)\)如果可以从中取一个或两个或三个物品.问能够组合出来的所有价值和对应的方案数,全部输出.取值时,\ ...
- 【LeetCode】282. Expression Add Operators
题目: Given a string that contains only digits 0-9 and a target value, return all possibilities to add ...
- 红黑树的C语言实现
rbtree.h #ifndef _RED_BLACK_TREE_H_ #define _RED_BLACK_TREE_H_ #define RED 0 // 红色节点 #define BLACK 1 ...
- ogg概叙、架构、进程
一. OGG 概述 OGG 全称Oracle Golden Gate. 历史: Golden Gate公司于1995年成立于美国加州旧金山,它的名称源自旧金山闻名于世的金门大桥.两位创始人Eric F ...
- bzoj 1731 [Usaco2005 dec]Layout 排队布局——差分约束
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1731 对差分约束理解更深.还发现美妙博客:http://www.cppblog.com/me ...
- git repo
- SQL DBA 学习
http://www.cnblogs.com/CareySon/category/389500.html SQL Pass(13) SQL SERVER(42) SQL Server DBA生涯(1) ...