Fibonacci数列
资源限制
时间限制:1.0 s 内存限制:256.0 MB
问题描述
Fibonacci数列的递推公式为:
,其中
当n比较大时,
也非常大,现在我们想知道,
除以10007的余数是多少。
输入格式
输入包含一个整数n
输出格式
输出一行,包含一个整数,表示
除以10007的余数。
说明:在本题中,答案是要求 除以10007的余数,因此我们只要能算出这个余数即可,而不需要先计算出 的准确值,再将计算的结果除以10007取余数,直接计算余数往往比先算出原数再取余简单。
样例输入
10
样例输出
55
样例输入
22
样例输出
7704
数据规模
解题思路:
第一反应是递归,结果发现自己有点憨憨递归肯定超时,结果真的30分,于是就想着优化 ,我会的有下面两种方式
- 利用类似于vector设置两个变量一个中间变量: 即可
- 利用曾经学过的矩阵快速幂加快运算,这里手推了一下又参考了网上的模板
提交代码-C++:
方案一:使用for循环
// 正常的 for 循环
#include<iostream>
using namespace std;
int main() {
int a=1,b=1,n;
int t;
cin >> n;
if (n==1 || n==2) cout<<1<<endl;
else{
for (int i=2;i<n;i++){
t = a;
a = b;
b = (b+t)%10007;
}
cout<<(b%10007)<<endl;
}
return 0;
}
方案一 :使用vector
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n;
cin>>n;
vector <int> lst;
lst.push_back(1);
lst.push_back(1);
for (int i=2;i<n;i++){
lst.push_back((lst.at(lst.size()-1)+lst.at(lst.size()-2))%10007);
}
cout<<lst.at(lst.size()-1)<<endl;
return 0;
}
方案二:
由于
数列的特殊性,公式为:
,其中
,所以有如下矩阵关系:
同理, 都可以通过继续乘以一个矩阵 得到,所以根据所学矩阵乘法计算 的幂方,可以根据矩阵 的幂方得到。
这里的转移矩阵就是 , 就是初始矩阵,而 则是乘以 次的常数矩阵得到的结果
// 试题 入门训练 Fibonacci数列
#include<iostream>
#include<vector>
#include<algorithm>
#include<string.h>
using namespace std;
const int N=2;
const int mod=10007;
int tmp[N][N],res[N][N];
// temp记录矩阵a和矩阵b的乘积结果 ,这里的b矩阵就是常数/转移矩阵
void multi(int a[][N],int b[][N],int N){
memset(tmp,0,sizeof(tmp));
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
for(int k=0;k<N;k++){
tmp[i][j]+=(a[i][k]*b[k][j])%mod; // 代表tmp[i][j]为A的第i行和B的第j列所有数
}
tmp[i][j]=tmp[i][j]%mod;
}
}
//更新A矩阵,为下一次使用做准备
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
a[i][j]=tmp[i][j];
}
//n是幂次数,N是矩阵大小,矩阵a代表的就是幂矩阵,将整数快速幂的整数换成矩阵即可
void Pow(int a[][N],int n){
memset(res, 0, sizeof res);
for (int i=0;i<N;i++) res[i][i]=1; //单位矩阵初始化,对角线值为1
while (n) {
if (n&1)
multi(res,a,N);//res=res*a;复制直接在multi里面实现了;
multi(a,a,N);//a=a*a
n>>=1;
}
}
// 矩阵快速幂
int main(){
int n;
cin>>n;
int a[N][N]={{1,1},{1,0}};
Pow(a,n);
cout << res[0][1]<<endl;
return 0;
}
参考文章/博客:
这里的文章主要是对快速幂和矩阵乘法下的快速幂进行了讲解了,有利于对这个点的认识
快速幂:
- https://www.cnblogs.com/yewanting/p/10743018.html
- https://blog.csdn.net/Harington/article/details/87602682
矩阵快速幂
- https://blog.csdn.net/zhangxiaoduoduo/article/details/81807338
- https://blog.csdn.net/qq_42817826/article/details/81566544
- https://www.cnblogs.com/cmmdc/p/6936196.html
总结
虽然是个水题,但是第一次的博客,在不断的学习/修改快速幂和矩阵快速幂部分内容,不仅是为了自己的更好理解,也是希望大家在浏览的时候能给出意见,指出不足