Time Limit:10000MS Memory Limit:65536K
Total Submit:62 Accepted:27
Case Time Limit:1000MS
Description
某天,幼儿园学生LZH周测数学时吓哭了,一道题都做不出来。这下可麻烦了他马上就会成为垫底的0分啊。他的期望也不高,做出最简单的第一题就够了
题目是这样的,定义 F ( n ) = ( ( 根 号 5 + 1 ) / 2 ) ( n − 1 ) F(n)=((根号5+1)/2)^(n-1) F(n)=((根号5+1)/2)(n−1) ,当然为了凸显题目的简单当然不能是小数分数或无理数, F ( x ) F(x) F(x)因此需要向上取整,当然求F(n)是非常难的!因此幼儿园园长头皮决定简单一点,求下 F ( x ) F(x) F(x)的前n项和就行了。
Input
输入 一个正整数n(保证 1 < = n < = 2 3 1 − 1 1<=n<=2^31-1 1<=n<=231−1)
Output
输出 一个正整数 S ( n ) S(n) S(n) 对 1000000007 1000000007 1000000007 取余就好了
样例
输入1
1
输出1
1
输入2
2
输出2
2
T i p s : Tips: Tips:暴力找规律
解题思路
乍一看,一个十分神奇的 ( ( 根 号 5 + 1 ) / 2 ) ( n − 1 ) ((根号5+1)/2)^(n-1) ((根号5+1)/2)(n−1),正准备跳题,然后经大佬说明题目打错了,其实是斐波那契的递推式。。。
然后打一波之前的 求斐波那契数列前n项的和 直接过了
代码
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const long long INF=1000000007;
long long n;
struct c{
long long n,m;
long long a[10][10];
}A,B,CC;
c operator *(c A,c B){
c C;
C.n=A.n,C.m=B.m;
for(int i=1;i<=C.n;i++)
for(int j=1;j<=C.m;j++)
C.a[i][j]=0;
for(int k=1;k<=A.m;k++)
for(int i=1;i<=C.n;i++)
for(int j=1;j<=C.m;j++)
C.a[i][j]=(C.a[i][j]+(A.a[i][k]*B.a[k][j]%INF))%INF;
return C;
}
void poww(long long x){
if(x==1)
{
B=A;
return ;
}
poww(x/2);
B=B*B;
if(x&1)
B=B*A;
}
int main(){
scanf("%lld",&n);
if(n==1)
{
printf("1");
return 0;
}
A.n=3,A.m=3;
A.a[1][1]=0,A.a[1][2]=1,A.a[1][3]=0;
A.a[2][1]=1,A.a[2][2]=1,A.a[2][3]=1;
A.a[3][1]=0,A.a[3][2]=0,A.a[3][3]=1;
poww(n-1);
CC.n=1,CC.m=3;
CC.a[1][1]=1,CC.a[1][2]=1,CC.a[1][3]=1;
CC=CC*B;
printf("%lld",CC.a[1][3]);
}