我是靠谱客的博主 勤劳胡萝卜,这篇文章主要介绍UOJ(WHYZ) P14 数列 递推+矩阵快速幂#14. 数列,现在分享给大家,希望可以做个参考。

#14. 数列

题目描述

a[1]=a[2]=a[3]=1

a[x]=a[x−3]+a[x−1](x>3)

       求a 数列的第 n 项对 1000000007 取余的值。

输入描述 第一行一个整数TT,表示询问个数。

以下TT行,每行一个正整数nn

输出描述

每行输出一个非负整数表示答案。

样例输入

复制代码
1
2
3
4
3 6 8 10

样例输出

复制代码
1
2
3
4 9 19

时间限制、数据范围及描述

时间:1s 空间:256M

n<=2*10^9


题目链接

这道题目可以说是矩阵快速幂中的模板题了。题目中先看到递推式,再看数据范围,很明显告诉你不能在O(n)时间内完成。因此我们考虑矩阵快速幂的算法。在这道题目中,我们至少只需要保留f[n-1]和f[n-3]两个值就能推出f[n],但因为f[n+1]需要用到f[n-2]的值,所以我们在矩阵中也必须保留。这样,我们便能推出解题的矩阵{{1,0,1},{1,0,0},{0,1,0}},再运用矩阵快速幂即可在logn时间内完成。

AC代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include<cstdio> #include<iostream> #include<cstring> #define ll long long using namespace std; const int mod=1000000007; struct jz{ ll x[5][5]; }; jz mult(jz a,jz b){ jz c; memset(c.x,0,sizeof(c.x)); for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ for(int k=0;k<3;k++){ c.x[i][j]=(c.x[i][j]+a.x[i][k]*b.x[k][j])%mod; } } } return c; } jz qpow(jz m,int n){ jz mul={{1,0,0,1}}; while(n){ if(n&1){ mul=mult(mul,m); } n>>=1; m=mult(m,m); } return mul; } int main(){ int n,t; scanf("%d",&t); while(t--){ jz m,ans; m.x[0][0]=m.x[0][2]=m.x[1][0]=m.x[2][1]=1; m.x[0][1]=m.x[1][1]=m.x[1][2]=m.x[2][2]=m.x[2][0]=0; scanf("%d",&n); ans=qpow(m,n-1); printf("%dn",ans.x[0][0]); } return 0; }


最后

以上就是勤劳胡萝卜最近收集整理的关于UOJ(WHYZ) P14 数列 递推+矩阵快速幂#14. 数列的全部内容,更多相关UOJ(WHYZ)内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(66)

评论列表共有 0 条评论

立即
投稿
返回
顶部