NYoj_301_递推求值 解题思路和代码
2018-01-22 13:50
351 查看
题目
描述给你一个递推公式:
f(x)=a*f(x-2)+b*f(x-1)+c
并给你f(1),f(2)的值,请求出f(n)的值,由于f(n)的值可能过大,求出f(n)对1000007取模后的值。
注意:-1对3取模后等于2
输入
第一行是一个整数T,表示测试数据的组数(T<=10000)
随后每行有六个整数,分别表示f(1),f(2),a,b,c,n的值。
其中0<=f(1),f(2)<100,-100<=a,b,c<=100,1<=n<=100000000 (10^9)
输出
输出f(n)对1000007取模后的值
样例输入
2 1 1 1 1 0 5 1 1 -1 -10 -100 3
样例输出
5 999896
要求
时间限制:1000 ms | 内存限制:65535 KB
解决方法
(一)使用递归方法
1、解题思路
拿到这个题目首先想到的是使用最直观的递归方式。2、程序代码
#include <iostream> using namespace std; int remainder(int n){ int temp = n%1000007; int res = temp > 0 ? temp: (temp+1000007); return res; } int funDiGui(int f1, int f2, int a, int b, int c, int n){ if(n==1){ return remainder(f1); } else if(n==2){ return remainder(f2); } else{ return remainder(a*funDiGui(f1, f2, a, b, c, n-2) + b*funDiGui(f1, f2, a, b, c, n-1) + c); } } int main() { int T; //T表示测试数据的组数 cin >> T; while(T--){ unsigned int *p = new unsigned int[6]; for (int i = 0; i < 6; ++i){ cin >> p[i]; } cout << funDiGui(p[0], p[1], p[2], p[3], p[4], p[5]) << endl; } return 0; }
3、运行结果
RunTimeError.(二)使用递推方法
1、解题思路
使用递归方法时间超时,递推方法好像比递归少消耗时间一点,所有又试了下递推的方式。2、程序代码
#include <iostream> using namespace std; int remainder(int n){ int temp = n%1000007; int res = temp > 0 ? temp: (temp+1000007); return res; } int funDiTui(int f1, int f2, int a, int b, int c, int n){ int *p = new int ; p[0] = remainder(f1); p[1] = remainder(f2); for ( int j = 2; j < n; ++j){ p[j] = remainder(a*p[j-2] + b*p[j-1] + c); } return p[n-1]; } int main() { int T; //T表示测试数据的组数 cin >> T; while(T--){ unsigned int *p = new unsigned int[6]; for (int i = 0; i < 6; ++i){ cin >> p[i]; } cout << funDiTui(p[0], p[1], p[2], p[3], p[4], p[5]) << endl; } return 0; }
3、运行结果
MemoryLimitExceeded.(三)使用矩阵方法
1、解题思路
递归和递推方法在性能上都不符合要求,在网上看了下解题报告,需要使用矩阵来解决,思路分析如下:f3=a∗f1+b∗f2+c
f4=a∗f2+b∗f3+c
...
通过矩阵表达如下:
令A=b10a00c01,B=f2f11
于是AB=b∗f2+a∗f1+c=f3f21,即第一行的值是f3;
A2B=A∗A∗B=b10a00c01∗f3f21=b∗f3+a∗f2+c=f4f31=…
故fn是An−2B 结果的第一行的值。
注意: 在下面的代码中,B使用的仍然是一个3*3的矩阵,不过只有第一列有意义,后两列都是0,对结果不产生影响。
2、程序代码
#include <iostream> #include <cstring> using namespace std; #define mod 1000007 #define N 3 typedef long long LL; struct Matrix{ LL mat ; }; Matrix unit_matrix = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; //单位矩阵 Matrix mul(Matrix a, Matrix b){ //矩阵相乘 Matrix res; memset(res.mat, 0, sizeof(res.mat)); for ( int i = 0; i < N; ++i) for (int j = 0; j < N; ++j){ res.mat[i][j] = 0; for (int k = 0; k < N; ++k){ res.mat[i][j] += a.mat[i][k] * b.mat[k][j]; res.mat[i][j] = (res.mat[i][j] + mod)%mod; //取模 } } return res; } Matrix pow_matrix(Matrix a, LL n){ //矩阵快速幂 Matrix res = unit_matrix; for (; n; n >>= 1){ if(n&1) res = mul(res, a); a = mul(a, a); } return res; } int main() { Matrix x, y; LL T, f1, f2, a, b, c, n; //T表示测试数据的组数 cin >> T; while(T--){ cin >> f1 >> f2 >> a >> b >> c >> n; memset(x.mat, 0, sizeof(x.mat)); memset(y.mat, 0, sizeof(y.mat)); x.mat[0][0] = b; //注意,在C++中,数组的下标从0开始,所以要特别注意 x.mat[0][1] = a; x.mat[0][2] = c; x.mat[1][0] = 1; x.mat[1][1] = 0; x.mat[1][2] = 0; x.mat[2][0] = 0; x.mat[2][1] = 0; x.mat[2][2] = 1; y.mat[0][0] = f2; y.mat[1][0] = f1; y.mat[2][0] = 1; if (n == 1){ cout << (f1+mod)%mod << endl; } else if ( n == 2){ cout << (f2+mod)%mod << endl; } else{ x = pow_matrix(x, n-2); x = mul(x, y); cout << (x.mat[0][0] + mod)%mod << endl; } } return 0; }
3、运行结果
运行通过,时间:355,内存:8648相关文章推荐
- nyoj 301 递推求值 和 nyoj 148 fibonacci数列(二) 【矩阵】
- NYoj_08_一种排序 解题思路和代码
- NYOJ 301 递推求值【矩阵快速幂】
- NYOJ301-递推求值
- NYoj_07_街区最短路径问题 解题思路和代码
- 矩阵快速幂 - hduoj 5667 Sequence -nyoj 301 递推求值
- NYOJ 301 递推求值【矩阵快速幂】
- nyoj301递推求值【矩阵快速幂】
- NYOJ - 301 - 递推求值 ( 递推+矩阵快速幂 )
- nyoj301 递推求值
- NYOJ 301 递推求值【矩阵快速幂取模】
- NYOJ-301递推求值
- nyoj--301--递推求值(经典矩阵运算)
- NYOJ 301 递推求值
- nyoj--301--递推求值(经典矩阵运算)
- nyoj 301 递推求值【常数矩阵】
- nyoj 301 递推求值 矩阵快速幂
- nyoj 301递推求值 (矩阵+快速幂)
- nyoj301——递推求值
- NYOJ-301 递推求值【矩阵二分幂】