NYOJ 301 递推求值(矩阵快速幂)
生活随笔
收集整理的這篇文章主要介紹了
NYOJ 301 递推求值(矩阵快速幂)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
遞推求值
時間限制:1000?ms ?|? 內(nèi)存限制:65535?KB 難度:4 描述給你一個遞推公式:
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
輸入隨后每行有六個整數(shù),分別表示f(1),f(2),a,b,c,n的值。
其中0<=f(1),f(2)<100,-100<=a,b,c<=100,1<=n<=100000000 (10^9)
分析:由于n的值比較大,所以常規(guī)方法肯定會超時。根據(jù)遞推式求第n個表達(dá)式的值時,通常用矩陣乘法來做。
本題要構(gòu)造兩個矩陣,其中一個為矩陣A,作為初始矩陣f2 ?0 ? 0
f1 ?0 ? 0
1 ? 0 ? 0
另一個為矩陣B
b ? a ? c
1 ? 0 ? 0
0 ? 0 ? 1
因?yàn)镕(2)和F(1)是已知的,當(dāng)n>=3時,每次都乘以矩陣B,就能推出下一個矩陣。而矩陣的第一行第一列的元素就是所求的結(jié)果。
所以利用矩陣快速冪能夠快速準(zhǔn)確地求出結(jié)果。
#include<stdio.h> #include<string.h> #define mod 1000007 #define N 3 typedef long long LL; struct Matrix {LL mat[N][N]; };Matrix unit_matrix = {1, 0, 0,0, 1, 0,0, 0, 1 }; //單位矩陣Matrix mul(Matrix a, Matrix b) //矩陣相乘 {Matrix res;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] %= mod;}}return res; }Matrix pow_matrix(Matrix a, LL n) //矩陣快速冪 {Matrix res = unit_matrix;while(n != 0){if(n & 1)res = mul(res, a);a = mul(a, a);n >>= 1;}return res; }int main() {LL n, f1, f2, a, b, c, T;Matrix tmp, arr;scanf("%lld",&T);while(T--){scanf("%lld%lld%lld%lld%lld%lld",&f1, &f2, &a, &b, &c, &n);if(n == 0)printf("%lld\n",(f2-f1*b-c + mod)%mod);if(n == 1)printf("%lld\n",(f1+mod)%mod);else if(n == 2)printf("%lld\n",(f2+mod)%mod);else{memset(arr.mat, 0, sizeof(arr.mat));arr.mat[0][0] = f2; arr.mat[1][0] = f1; arr.mat[2][0] = 1;tmp.mat[0][0] = b; tmp.mat[0][1] = a; tmp.mat[0][2] = c;tmp.mat[1][0] = tmp.mat[2][2] = 1;tmp.mat[1][1] = tmp.mat[1][2] = tmp.mat[2][0] = tmp.mat[2][1] = 0;Matrix p = pow_matrix(tmp, n-2);p = mul(p, arr);LL ans = (p.mat[0][0] + mod) % mod;printf("%lld\n",ans);}}return 0; }總結(jié)
以上是生活随笔為你收集整理的NYOJ 301 递推求值(矩阵快速幂)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一口气说出 6种 延时队列的实现方法,面
- 下一篇: STL之set集合容器