【HDU 1005 && ZOJ 3539】简单矩阵dp
2012-12-10 12:53
489 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1005
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3538
1005题目大意:
告诉你f[1]=1, f[2]=1, f
=(A*f[n-1]+B*f[n-2])%7;然后输入A,B,n,让你求f
。
解题思路:
解法1:n比较大,给你这样递推式子一般不可能让你全部求出来,一般是有规律可寻的。只要在递推的过程中发现f[n-1]==f[1],f
==f[2],停止递推。把它多少个数循环一次记录下来,然后只需要用n对这个数取余即可。
解法2: 巧用矩阵dp 。 一般的矩阵dp是要你自己推出这个递推式,然后再构造矩阵。这题更简单一些,因为题目已经给好了你递推式,f[1],f[2]为特殊项,这里我们不考虑,把f[3]当做第一项来考虑。
f[3]=A+B, f[4]=A*(A+B)+B
这里递推式可以分解为两项,可以先把[A B](f[3]的两项)提出来,一般的矩阵dp为2阶,所以这样还是不够的。再观察递推式,求f[n+1]时我们还要用到前面两项,f
就在之前,所以我们还要把前面出现的f[n-1]保存下来,即让A对应的为1。这样就可以构造矩阵 | A B | 了。
| 1 0 |
View Code
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3538
1005题目大意:
告诉你f[1]=1, f[2]=1, f
=(A*f[n-1]+B*f[n-2])%7;然后输入A,B,n,让你求f
。
解题思路:
解法1:n比较大,给你这样递推式子一般不可能让你全部求出来,一般是有规律可寻的。只要在递推的过程中发现f[n-1]==f[1],f
==f[2],停止递推。把它多少个数循环一次记录下来,然后只需要用n对这个数取余即可。
解法2: 巧用矩阵dp 。 一般的矩阵dp是要你自己推出这个递推式,然后再构造矩阵。这题更简单一些,因为题目已经给好了你递推式,f[1],f[2]为特殊项,这里我们不考虑,把f[3]当做第一项来考虑。
f[3]=A+B, f[4]=A*(A+B)+B
这里递推式可以分解为两项,可以先把[A B](f[3]的两项)提出来,一般的矩阵dp为2阶,所以这样还是不够的。再观察递推式,求f[n+1]时我们还要用到前面两项,f
就在之前,所以我们还要把前面出现的f[n-1]保存下来,即让A对应的为1。这样就可以构造矩阵 | A B | 了。
| 1 0 |
View Code
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define mod 1000000007 typedef long long lld; struct Node { int d; char str[5]; bool operator<(const Node &S)const { return d<S.d; } }f[20]; struct Maxtri { lld mat[2][2]; }; Maxtri A, B; void init() { A.mat[0][0]=1,A.mat[0][1]=0; A.mat[1][0]=0,A.mat[1][1]=1; B.mat[0][0]=0,B.mat[0][1]=1; B.mat[1][0]=3,B.mat[1][1]=2; } lld Maxtri_mod(lld a, int b) { lld ans=1; while(b) { if(b&1) ans=(ans*a)%mod; b>>=1; a=(a*a)%mod; } return ans; } Maxtri Maxtri_mul(Maxtri a, Maxtri b) { Maxtri c; for(int i=0; i<2; i++) for(int j=0; j<2; j++) { c.mat[i][j]=0; for(int k=0; k<2; k++) c.mat[i][j]+=(a.mat[i][k]*b.mat[k][j])%mod; c.mat[i][j]%=mod; } return c; } lld Maxtri_mi(int b, int p) { Maxtri ans=A, tp=B; while(b) { if(b&1) ans=Maxtri_mul(ans,tp); b>>=1; tp=Maxtri_mul(tp,tp); } if(p==0) return ans.mat[1][0]%mod; else return ans.mat[1][1]%mod; } int main() { int n, m; init(); while(~scanf("%d%d",&n,&m)) { if(m==0) { lld ans=Maxtri_mod(3,n-1)*4%mod; printf("%lld\n",ans); continue; } for(int i=0; i<m; i++) scanf("%d %s",&f[i].d,f[i].str); sort(f,f+m); lld ans=Maxtri_mod(3,f[0].d-1)%mod; for(int i=1; i<m; i++) { if(f[i].d-f[i-1].d-1==0) ///!!! { if(*f[i].str==*f[i-1].str) { cout << 0 <<endl; goto loop; ///直接跳出循环到loop } else continue; } else { if(*f[i].str==*f[i-1].str) /// 开始忘记打*号比较值,不打则是比较地址 ans=ans*Maxtri_mi(f[i].d-f[i-1].d-1,0)%mod; else ans=ans*Maxtri_mi(f[i].d-f[i-1].d-1,1)%mod; } } ans=ans*Maxtri_mod(3,n-f[m-1].d)%mod; printf("%lld\n",ans); loop:{} } return 0; }
相关文章推荐
- HDU 1078 FatMouse and Cheese 简单DP&记忆化搜索
- HDU 1087 Super Jumping! Jumping! Jumping! && 1114 Piggy-Bank 简单dp
- 【HDU 1058 & HDU 3199 类似丑数】 简单DP思想
- HDU 2157 How many ways??(简单线性DP | | 矩阵快速幂)
- ZOJ 1108 FatMouse's Speed (HDU 1160) DP
- ZOJ 4772 Treasure Hunt I 树形DP(背包) && hdu The Ghost Blows Light 树形DP(背包)
- HDU 6148 && 2017 百度之星复赛 1005 Valley Numer(数位dp)
- HDU 2157 How many ways??(简单线性DP | | 矩阵快速幂)
- hdu 4576(简单概率dp | 矩阵优化)
- hdu 1505 City Game 简单DP 最大子矩阵 迭代法
- hdu 3698 Let the light guide us(线段树优化&简单DP)
- ZOJ 3690 & HDU 3658 (矩阵高速幂+公式递推)
- 多校第6场 HDU 3893&&JLU Drawing Pictures(数位DP变形,矩阵连乘)
- ZOJ 2994 && HDU 1992 Tiling a Grid With Dominoes (状压DP)
- hdu 1160 FatMouse's Speed 题解(简单dp)
- ZOJ 3690 & HDU 3658 (矩阵快速幂+公式递推)
- hdu 1160 FatMouse's Speed 简单dp 题解
- hdu 2571&hdu 2577(简单经典dp)
- hdu 5171 GTY's birthday gift (构造矩阵)
- hdu 4421 && zoj 3656 Bit Magic 2-sat题找规律水过 也可以用并查集