打表找规律+矩阵快速幂 - hdu6198

number number number


题意:

给出斐波那契数组的定义,F0=0,F1=1;Fn=Fn1+Fn2 (n2).

给定一个k,求出不能由k个斐波那契数组成的最小的数。


数据范围:

多组输入,由EOF结束。1k109


时间:1s


题解:

首先打一个表,找出前面几项的结果,然后就能发现规律。


打表代码:

#include<iostream>
#include<stdio.h>
#include<string.h>

const int maxn = 100000;
const int mod = 998244353;
typedef long long ll;
using namespace std;
ll n,k,f[maxn+5];
int p[maxn];
int main()
{
    f[0] = 0, f[1] = 1;
    for(int i=2; i<=30; i++) f[i]=f[i-1]+f[i-2];
    for(int i=1; i<=20; ++i)printf("%d %d\n",i,f[i]);
    printf("\n");

    int maxp=0;
    for(int i=1; i<=300; i++)
    {
        p[i]=i;
        for(int j=1; f[j]<=i; j++)
            p[i]=min(p[i],p[i-f[j]]+1);
        printf("%d %d",i,p[i]);
        if(maxp<p[i])
        {
            printf("--------------");
            maxp=p[i];
        }
        puts("");
    }
    return 0;
}


AC代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#define LL long long

using namespace std;

const LL mod=998244353;
const int maxn=2;
struct Mat
{
    LL mp[maxn][maxn];
} res,A;

Mat Mul(Mat a,Mat b)
{
    int n=2;
    Mat c;
    memset(c.mp,0,sizeof(c.mp));
    for(int i=0; i<n; ++i)
        for(int j=0; j<n; ++j)
            for(int k=0; k<n; ++k)
            {
                c.mp[i][j]+=(a.mp[i][k]*b.mp[k][j])%mod;
                c.mp[i][j]%=mod;
            }
    return c;
}

LL Pow(LL k)
{
    while(k>0)
    {
        if(k&1) res=Mul(A,res);
        A=Mul(A,A);
        k/=2;
    }
    return ((res.mp[0][0]-1)%mod+mod)%mod;
}

void Init()
{
    res.mp[0][0]=res.mp[1][1]=1;
    res.mp[0][1]=res.mp[1][0]=0;

    A.mp[0][0]=A.mp[0][1]=A.mp[1][0]=1;
    A.mp[1][1]=0;
}

int main()
{
    LL k;
    while(scanf("%lld",&k)!=EOF)
    {
        Init();
        printf("%lld\n",Pow(k*2+2));
    }

    return 0;
}




猜你喜欢

转载自blog.csdn.net/exchan/article/details/77968723