nyoj301 递推求值(矩阵快速幂)
2016-02-12 17:14
381 查看
题目链接:
http://acm.nyist.net/JudgeOnline/problem.php?pid=301
题目大意:
计算递推式f(x)=a*f(x-2)+b*f(x-1)+c,求f(n)。
范围:
0<=f(1),f(2)<100,-100<=a,b,c<=100,1<=n<=100000000 (10^9)
思路:
由于n很大,所以不能够直接采用递推的方法。
由于是一个方程式,所以可以转化为矩阵乘法,又是一个递推式,就想到用矩阵快速幂解决。
矩阵快速幂:
就是矩阵的快速乘法,跟数的求快速幂是一样的。
--------------------------------------------------------------------------------------------------------------
所以这个递推式可以转化为矩阵A
b a c
1 0 0
0 0 1
和矩阵B
f2
f1
1
的乘积A*B.
得到的就是答案f(3)。
然后我们就可以通过递推的方式计算出f(n)。可以知道f(n)=A^(n-2)*B,利用矩阵快速幂算出A^(n-2),就解决问题了。
代码:
http://acm.nyist.net/JudgeOnline/problem.php?pid=301
题目大意:
计算递推式f(x)=a*f(x-2)+b*f(x-1)+c,求f(n)。
范围:
0<=f(1),f(2)<100,-100<=a,b,c<=100,1<=n<=100000000 (10^9)
思路:
由于n很大,所以不能够直接采用递推的方法。
由于是一个方程式,所以可以转化为矩阵乘法,又是一个递推式,就想到用矩阵快速幂解决。
矩阵快速幂:
就是矩阵的快速乘法,跟数的求快速幂是一样的。
--------------------------------------------------------------------------------------------------------------
所以这个递推式可以转化为矩阵A
b a c
1 0 0
0 0 1
和矩阵B
f2
f1
1
的乘积A*B.
得到的就是答案f(3)。
然后我们就可以通过递推的方式计算出f(n)。可以知道f(n)=A^(n-2)*B,利用矩阵快速幂算出A^(n-2),就解决问题了。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #define n 100 #define ll long long #define mod 1000007 using namespace std; struct Mat{ ll mat[5][5]; }; int ss; Mat operator * (Mat a, Mat b) { Mat c; memset(c.mat, 0, sizeof(c.mat)); int i, j, k; for(k = 0; k < 4; ++k) { for(i = 0; i < 4; ++i) { for(j = 0; j < 4; ++j) { c.mat[i][j] += (a.mat[i][k] * b.mat[k][j]); c.mat[i][j]=(c.mat[i][j]+mod)%mod; } } } return c; } Mat operator ^ (Mat a, ll k) { Mat c; int i, j; for(i = 0; i < 4; ++i) for(j = 0; j < 4; ++j) c.mat[i][j] = (i == j); //初始化为单位矩阵 for(; k; k >>= 1) { if(k&1) c = c*a; a = a*a; } return c; } int main() { Mat x,y; int i,j,k,N,T,f1,f2,a,b,c; scanf("%lld",&T); while(T--) { scanf("%d%d%d%d%d%d",&f1,&f2,&a,&b,&c,&N); memset(x.mat,0,sizeof(x.mat)); memset(y.mat,0,sizeof(y.mat)); x.mat[1][1]=b; x.mat[1][2]=a; x.mat[1][3]=c; x.mat[2][1]=1; x.mat[2][2]=0; x.mat[2][3]=0; x.mat[3][3]=1; y.mat[1][1]=f2; y.mat[2][1]=f1; y.mat[3][1]=1; // scanf("%d",&N); if(N==1){ printf("%d\n",f1); continue; } x=x^(N-2); x=x*y; printf("%lld\n",(x.mat[1][1]+mod)%mod); } }
相关文章推荐
- 【设计模式】2、生成器模式(建造者模式)
- c++ string 用法总结
- QT的Meta-Object系统
- 需要经常看的故事
- vs2013连接mysql mysql_init未定义
- Android TV Studuy1-2
- ATL与COM之间的关系、ATL的特点与基本使用方法
- Xcode7中你一定要知道的炸裂调试神技
- android:从另外一个activity中返回数据
- [LeetCode]Gas Station
- 从初识Linux到离不开系列(四)循序渐进
- 相当重要---部署OGG对Oracle Database 补丁的要求
- 算法学习--贪心算法
- Python教程学习简记8--Python 高阶函数 map/reduce filter sorted
- 深入理解Java虚拟机----(十一)线程安全与锁优化
- 舍身喂虎
- 后缀数组
- 2.ORM思想
- FMDB初步使用小结
- debian/ubuntu/deepin中Harminv 编译与安装