矩阵快速幂+map 雷神之路 scu dp练习A题
2016-05-18 21:21
435 查看
传送门:点击打开链接
题意:刚开始在位置0,只允许向右走,可以走1步,2步或3步,路上有地雷,不能踩(m <= 500)。问到达位置n的方法数(n <= 1e18),答案取模1e9+7
思路:很明显要用矩阵快速幂来加速计算dp。
我们假如知道了位置pos[i]有一个雷,那么我们就要算出dp[pos[i]-1]和dp[pos[i]-2]的值,并让dp[pos[i]]=0
对于下一个雷,我们就直接从这里开始用矩阵快速幂算到下一个雷的位置。
因为里面的情况比较多,我们可以直接用map来类似记忆化一样,保存节点的答案,可以避免各种判断
题意:刚开始在位置0,只允许向右走,可以走1步,2步或3步,路上有地雷,不能踩(m <= 500)。问到达位置n的方法数(n <= 1e18),答案取模1e9+7
思路:很明显要用矩阵快速幂来加速计算dp。
我们假如知道了位置pos[i]有一个雷,那么我们就要算出dp[pos[i]-1]和dp[pos[i]-2]的值,并让dp[pos[i]]=0
对于下一个雷,我们就直接从这里开始用矩阵快速幂算到下一个雷的位置。
因为里面的情况比较多,我们可以直接用map来类似记忆化一样,保存节点的答案,可以避免各种判断
#include <map> #include <set> #include <cmath> #include <ctime> #include <stack> #include <queue> #include <cstdio> #include <cctype> #include <bitset> #include <string> #include <vector> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> #define fuck(x) cout<<"["<<x<<"]"; #define FIN freopen("input.txt","r",stdin); #define FOUT freopen("output.txt","w+",stdout); //#pragma comment(linker, "/STACK:102400000,102400000") using namespace std; typedef long long LL; typedef pair<int, int> PII; const int mod = 1e9 + 7; const int MX = 1e5 + 5; typedef vector<int> vec; typedef vector<vec> mat; mat mat_mul(mat &A, mat &B) { mat C(A.size(), vec(B[0].size())); for(int i = 0; i < A.size(); i++) { for(int j = 0; j < B[0].size(); j++) { for(int k = 0; k < B.size(); k++) { C[i][j] = ((LL)A[i][k] * B[k][j] + C[i][j]) % mod; } } } return C; } mat mat_pow(mat A, LL n) { mat B(A.size(), vec(A.size())); for(int i = 0; i < A.size(); i++) B[i][i] = 1; while(n) { if(n & 1) B = mat_mul(B, A); A = mat_mul(A, A); n >>= 1; } return B; } int f(int a, int b, int c, LL n) { mat A(3, vec(3)), B(3, vec(1)); A[0][0] = A[0][1] = A[0][2] = 1; A[1][0] = 1; A[1][1] = A[1][2] = 0; A[2][0] = 0; A[2][1] = 1; A[2][2] = 0; B[0][0] = c; B[1][0] = b; B[2][0] = a; A = mat_pow(A, n); B = mat_mul(A, B); return B[0][0]; } LL pos[MX]; int main() { int T, m; //FIN; scanf("%d", &T); while(T--) { LL n; map<LL, int> ans; scanf("%lld%d", &n, &m); for(int i = 1; i <= m; i++) { scanf("%lld", &pos[i]); } sort(pos + 1, pos + 1 + m); pos[m + 1] = n + 1; ans[-2] = ans[-1] = 0; ans[0] = 1; int now = 0, a = 0, b = 0, c = 1; for(int i = 1; i <= m + 1; i++) { if(!ans.count(pos[i] - 2)) ans[pos[i] - 2] = f(a, b, c, pos[i] - 2 - now); if(!ans.count(pos[i] - 1)) ans[pos[i] - 1] = f(a, b, c, pos[i] - 1 - now); ans[pos[i]] = 0; now = pos[i]; a = ans[pos[i] - 2]; b = ans[pos[i] - 1]; c = 0; } printf("%d\n", ans ); } return 0; }
相关文章推荐
- POJ1426 建议打表做该题/用数组模拟队列(比STL队列速度要快)
- Yii2.0 自定义日志类
- Libgdx之Label Image
- 面向项目(十一)—— 库的使用
- JAVA-007前面所学总结加深
- 第十三周的学习进度表
- IOI2000 邮局
- iOS蓝牙开发(一)蓝牙相关基础知识
- 渣渣的艰难的找实习经历
- 5月17日 AJAX 之 XML
- ab中文手册
- AngularJS之表单验证
- 快速排序算法(排序详解)
- sdut oj 2404 super prime(素数筛)
- 删除vi编辑产生的.swp文件
- 快速排序
- jquery语法
- 架构大数据分析应用
- JAXB - Validate Document before It is Unmarshalled
- Long Short-Term Memory (LSTM)公式简介