题目描述
I:某天,幼儿园学生LZH周测数学时吓哭了,一道题都做不出来。这下可麻烦了他马上就会成为垫底的0分啊。他的期望也不高,做出最简单的第一题就够了
题目是这样的,定义F(n)=((根号5+1)/2)^(n-1) ,当然为了凸显题目的简单当然不能是小数分数或无理数,F(x)因此需要向下取整,当然求F(n)是非常难的!因此幼儿园园长头皮决定简单一点,求下F(x)的前n项和就行了。
样例输入1
1
样例输出1
1
样例输入2
2
样例输出2
2
II:这天,当一头雾水的LZH同学在考场上痛哭的时候,一旁的YMW早就如切菜一样cut掉了简单至极的第一题,风轻云淡的冲击着满分,然而最后一道题着实难道了他,毕竟是幼儿园副园长树皮和著名毒瘤秋彪为了防止人AK而出的,可是YMW作为ACrush的著名粉丝,向来以AK为目标,永不言败,而他能不能AK就看你了
题目是酱紫的:
f(n)-f(3)-f(4)-f(5)-…-f(n-3)-f(n-2)=(n+4)(n-1)/2,f(1)=1,f(2)=1
求f(n)的前n项和
Input
输入 一个正整数n(保证0<=n<=2^31-1)
Output
输出 一个正整数,表示f(x)前n项的和,需要对1000000007求余
样例输入1
1
样例输出1
1
样例输入2
2
样例输出2
2
分析
I:(更改题面错误:向下取整)
根据推规律,我们发现,每一项的值其实就是斐波那契的值,那么其实题目就是在要求我们求出斐波那契前n项的和
显然可以设1*3矩阵 {f(n-1),f(n),s(n-1)
通过乘以一个3*3矩阵A得到:{f(n),f(n+1),s(n)
这个矩阵显然是
0,1,0
1,1,1
0,0,1
II:
根据之前的题目容易想到矩阵:
{fn-2,fn-1,sn-2,n,1
乘以一个矩阵A得到:
{fn-1,fn,sn-1,n+1,1
显然矩阵为:
0,1,0,0,0
1,1,1,0,0
0,0,1,0,0
0,1,0,1,1
#include <iostream>
#include <cstdio>
#include <memory.h>
#define rep(i,a,b) for (i=a;i<=b;i++)
#define q 1000000007
using namespace std;
int n;
long long a[1][3]={1,1,1};
long long b[3][3]={{0,1,0},{1,1,1},{0,0,1}},c[3][3]={{0,1,0},{1,1,1},{0,0,1}};
void ksm(int p)
{
if (p<=1) return;
ksm(p/2);
long long d[3][3];
int i,j,k;
d[0][0]=c[0][0];d[0][1]=c[0][1];d[0][2]=c[0][2];
d[1][0]=c[1][0];d[1][1]=c[1][1];d[1][2]=c[1][2];
d[2][0]=c[2][0];d[2][1]=c[2][1];d[2][2]=c[2][2];
memset(c,0,sizeof(c));
rep(i,0,2)
rep(j,0,2)
rep(k,0,2)
c[i][j]=(c[i][j]+d[i][k]*d[k][j])%q;
if (p%2)
{
d[0][0]=c[0][0];d[0][1]=c[0][1];d[0][2]=c[0][2];
d[1][0]=c[1][0];d[1][1]=c[1][1];d[1][2]=c[1][2];
d[2][0]=c[2][0];d[2][1]=c[2][1];d[2][2]=c[2][2];
memset(c,0,sizeof(c));
rep(i,0,2)
rep(j,0,2)
rep(k,0,2)
c[i][j]=(c[i][j]+d[i][k]*b[k][j])%q;
}
return;
}
int main()
{
int n,i,j;
long long d[1][3]={1,1,1};
scanf("%d",&n);
ksm(n-1);
if (n>1)
rep(i,0,2)
{
d[0][i]=0;
rep(j,0,2)
d[0][i]=(d[0][i]+a[0][j]*c[j][i])%q;
}
printf("%lld",d[0][2]);
return 0;
}