NYOJ 301 递推求值

来源:互联网 发布:linux eclipse 下载 编辑:程序博客网 时间:2024/04/20 04:53

递推求值

时间限制:1000 ms  |  内存限制: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

输入
第一行是一个整数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取模后的值


解题思路:                        |b,1,0|

矩阵|Fn, Fn-1, 1|乘以矩阵|a,0,0|等于矩阵|Fn+1,Fn,1|

                                         |c,0,1|

所以就化成矩阵的运算,矩阵连乘符合结合律又可以相似于快速幂来实现,如果快速幂你不懂,建议先网上看一下,了解一下思想。


AC代码:


# include <stdio.h>using namespace std;typedef long long int ll;const ll mod=1000007;struct mat{ll a[3][3];};mat mul(mat a, mat b){mat ans;for(ll i=0; i<3; i++){for(ll j=0; j<3; j++){ans.a[i][j]=0;for(ll k=0; k<3; k++){ans.a[i][j]=ans.a[i][j]+a.a[i][k]*b.a[k][j]%mod;ans.a[i][j]=(ans.a[i][j]+mod)%mod;}}}return ans;}mat Pow(mat a, ll n){mat B={1, 0, 0,0, 1, 0, 0, 0, 1};while(n>0){if(n&1)B=mul(B, a);a=mul(a, a);n>>=1;}return B;}int main(){    ll i, j, k, n, t, f1, f2, a, b, c;scanf("%lld", &t);while(t--){scanf("%lld%lld%lld%lld%lld%lld", &f1, &f2, &a, &b, &c, &n);mat A;A.a[0][0]=b; A.a[0][1]=1; A.a[0][2]=0;A.a[1][0]=a; A.a[1][1]=0; A.a[1][2]=0;A.a[2][0]=c; A.a[2][1]=0; A.a[2][2]=1;if(n==1)printf("%lld\n", f1);else if(n==2)printf("%lld\n", f2);else{mat ans=Pow(A, n-2);ll res=0;res=res+(f2*ans.a[0][0]+mod)%mod;res=res+(f1*ans.a[1][0]+mod)%mod;res=res+(ans.a[2][0]+mod)%mod;printf("%lld\n", res%mod);}}return 0;}


0 0
原创粉丝点击