[SCU 4508] 雷神之路 (多矩阵快速幂)
2016-05-23 12:41
330 查看
SCU - 4508
一条长度 N(N<1e18)的路,一次可以向前走一步、两步或者三步。有些地方有地雷不能走,问走到终点的方案数是多少。
这题 N高达 1e18,反而直接提示了做法。这题非矩阵快速幂不可。
构造两个矩阵,norm表示下一格没有雷,向前递推一步
而 zero表示下一格有雷,向前递推一步
然后对地雷的位置排序,第 i个地雷据上一个地雷的距离为 s
则对答案向量左乘 norm^(s-1)*zero
其中
norm=⎡⎣⎢⎢110101100⎤⎦⎥⎥
zero=⎡⎣⎢⎢010001000⎤⎦⎥⎥
初始向量为
X=⎡⎣⎢⎢F0F−1F−2⎤⎦⎥⎥=⎡⎣⎢⎢100⎤⎦⎥⎥
#pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <iostream> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include <queue> using namespace std; typedef pair<int,int> Pii; typedef long long LL; typedef unsigned long long ULL; typedef double DBL; typedef long double LDBL; #define MST(a,b) memset(a,b,sizeof(a)) #define CLR(a) MST(a,0) #define Sqr(a) (a*a) const int maxm=500+10, MOD=1e9+7; struct Matrix { LL n[3][3]; Matrix(){CLR(n);} Matrix operator * (const Matrix &v) const { Matrix temp; for(int i=0; i<3; i++) for(int j=0; j<3; j++) for(int k=0; k<3; k++) temp.n[i][j]=(temp.n[i][j]+n[i][k]*v.n[k][j])%MOD; return temp; } void E(){CLR(n);for(int i=0; i<3; i++) n[i][i]=1;} void pri(){puts("Matrix:");for(int i=0; i<3; i++) {for(int j=0; j<3; j++)printf("%lld", n[i][j]);puts("");}} }; LL N; int M; LL inpt[maxm]; Matrix MPow(Matrix,LL); int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); #endif int T; scanf("%d", &T); for(int ck=1; ck<=T; ck++) { scanf("%lld%d", &N, &M); for(int i=0; i<M; i++) scanf("%lld", &inpt[i]); sort(inpt, inpt+M); M=unique(inpt, inpt+M)-inpt; while(M && inpt[M-1]>N) M--; if(!M) { puts("1"); continue; } if(inpt[0]==0 || inpt[M-1]==N) { puts("0"); continue; } Matrix res,zero,norm; res.E(); zero.n[1][0] = zero.n[2][1] = 1; norm=zero; for(int i=0; i<3; i++) norm.n[0][i]=1; for(int i=0; i<M; i++) { int tims=inpt[i]-1; if(i) tims-=inpt[i-1]; res=MPow(norm, tims)*res; res=zero*res; } res=MPow(norm, N-inpt[M-1])*res; printf("%lld\n", res.n[0][0]); } return 0; } Matrix MPow(Matrix mat, LL tims) { Matrix res; res.E(); while(tims) { if(tims&1) res=res*mat; mat=mat*mat; tims>>=1; } return res; }
相关文章推荐
- 【leetcode】16. 3Sum Closest
- 上海普通住房标准
- PAT (Advanced Level) 1036. Boys vs Girls (25)
- Ext JS4 架构你的应用 第3节 (官方文档翻译)
- ScrollView,ListView等带滚动条控件嵌套解决方案汇总
- Eclipse更换应用包名
- Activity的生命周期
- [POJ 2096] Collecting Bugs
- c#反射相关
- IOS 访问java提供的webservice接口,心魔之使
- Linux 3.9.10内核编译错误:multiple (or no) load addresses: This is incompatible with uImages的解决
- Database: Faces & Sketchs 人脸识别数据集
- Java的SPI(Service Provider Interface)规范
- Android屏幕自适应研究
- 学习Android SQLite 的介绍和使用(二)
- nginx禁止未绑定域名访问 并且强行断开连接
- SICP chapter2 put get
- 字体颜色对话框
- android studio 查找sha1
- su root 和su - root 的区别