[斐波那契][矩阵乘法]幼儿园数学题I&II

题目描述

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;
}

猜你喜欢

转载自blog.csdn.net/ssl_qyh0ice/article/details/80285902
今日推荐