题目链接
看到n的数据量就知道不是简单递推了。
这里介绍俩种方法:
1. 求解数列的递推公式
通过特征方程可以得到这个公式
但是发现这里既有浮点数也有除数,取膜的时候就不对了
a.对于除数,我们可以找到逆元,求出逆元即可
b.
对于浮点数sqrt(5),x=616991993是它的逆元,那么用这个数代替sqrt(5)即可
对于浮点数1/5 找到逆元是y=200000002
所以an = x*y*( (616991994/2)^n - (-616991992/2)^n)即可
2. 利用矩阵的性质(如下特点),
所以需要求fn的话,跑一下n次方的矩阵,然后返回矩阵的斜对角任意各一个值即可(他们相等)
#include<iostream>
using namespace std;
#define mod 1000000009
long long pow(long long n){
long long ans[2][2] = {{1,0},{0,1}};
long long a[2][2] ={{1,1},{1,0}};
long long b[2][2] ={{1,1},{1,0}};
while(n){
if(n&1){
for(int i = 0;i<2;i++)
for(int j = 0;j<2;j++){
b[i][j] = 0;
for(int k = 0;k<2;k++)
b[i][j] = (b[i][j] + ans[i][k]*a[k][j])%mod;
}
for(int i = 0;i<2;i++){
for(int j = 0;j<2;j++)
ans[i][j] = b[i][j]%mod;
}
}
n>>=1;
for(int i = 0;i<2;i++)
for(int j = 0;j<2;j++){
b[i][j] = 0;
for(int k = 0;k<2;k++)
b[i][j] = (b[i][j] + a[i][k]*a[k][j]%mod)%mod;
}
for(int i = 0;i<2;i++){
for(int j = 0;j<2;j++)
a[i][j] = b[i][j]%mod;
}
}
return ans[1][0];
}
int main(){
long long n;
cin>>n;
cout<<pow(n);
}