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时的选法 ...
随机推荐
- Mysql处理字符串函数(转)
http://www.jb51.net/article/27458.htm 感觉上MySQL的字符串函数截取字符,比用程序截取(如PHP或JAVA)来得强大,所以在这里做一个记录,希望对大家有用. 函 ...
- HihoCoder1649 : 漏写的数字([Offer收割]编程练习赛38)(模拟题)
描述 小A今年刚上幼儿园,正在学习写100以内的数字.幼儿园的老师留了一项作业,要求小A从某个100以内的数X开始一直写到另一个100以内的数Y(Y - X > 1). 不过粗心的小A在作业中漏 ...
- 【Lintcode】038.Search a 2D Matrix II
题目: Write an efficient algorithm that searches for a value in an m x n matrix, return the occurrence ...
- 规划ASM DISK GROUP、查看asm 磁盘当前状态、mount or dismount 磁盘组、检查磁盘组 metadata 的内部一致性
规划ASM DISK GROUP: 1. 每个磁盘组里的磁盘应该大小.性能.新旧等一致,不能有太大差距 2. 对database files 和 fast recovery area 分别创建不同的d ...
- C++ 创建文件的方法
CString getPath(){ CTime time = CTime::GetCurrentTime(); CString t = time.Format(_T("%Y%m%d%H%M ...
- TCP头部格式详解,附Wireshark对TCP头部抓包分析
TCP之所以能为数据通讯提供可靠的传输,主要在于TCP数据包头部功能非常多. 那么,我们先来看看TCP头部格式(RFC 793.1323定义了TCP头部): TCP头部格式中的内容解析如下:(文末还有 ...
- sulime的必备插件
常用插件 : SideBarEnhancements HTML-CSS-JS Prettify BracketHighlighter SublimeCodeIntel Emmet CTags Mark ...
- POJ-2229
Sumsets Time Limit: 2000MS Memory Limit: 200000K Total Submissions: 19599 Accepted: 7651 Descrip ...
- RHEL 6 搭建ftp服务 xinetd,telnet
1.挂载光盘 设置vmware中光驱选项,载入rhel6光盘镜像 6 搭建ftp服务 xinetd,telnet" /> 2.安装rpm包 输入"#cd /media/&qu ...
- yii使用CFrom调用ajax失败的记录
在学习配置yii的CFrom的时候,发现怎么也不能让ajax生效,后来看文档后 ,终于发现了问题的所在. 问题配置文件如下 public function getUserConfig(){ retur ...