Byfibonacci 题解(斐波那契性质+dp)

题目链接

题目思路

首先一个及其暴力的思路\(dp[i][j]\)表示前\(i\)个斐波那契数构成\(j\)的答案然后极限卡常就过了???

正解是要观察斐波那契的性质,对于斐波那契的前缀和\(pre[i]=fac[i+2]-1\)

那么如果要构成\(n\),必定要选择小于等于他的两个最大的斐波那契数之一,并且相互对立

\(dp[i][0]\)表示选了小于等于\(i\)的次大的,\(dp[i][1]\)表示选了小于等于i的最大的

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define S s
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e7+5,inf=0x3f3f3f3f,mod=998244353;
int n;
ll fac[40];
ll dp[maxn][2];
signed main(){
    fac[0]=fac[1]=1;
    for(int i=2;i<=35;i++){
        fac[i]=fac[i-1]+fac[i-2];
    }
    dp[0][0]=1;
    int id=1;
    for(int i=1;i<=1e7;i++){
        if(i>=fac[id+1]){
            id++;
        }
        if(i-fac[id-1]>=fac[id-1]){
            dp[i][0]=fac[id-1]*dp[i-fac[id-1]][0]%mod;
        }else{
            dp[i][0]=(fac[id-1]*dp[i-fac[id-1]][0]+fac[id-1]*dp[i-fac[id-1]][1])%mod;
        }

        if(i-fac[id]>=fac[id]){
            dp[i][1]=fac[id]*dp[i-fac[id]][0]%mod;
        }else{
            dp[i][1]=(fac[id]*dp[i-fac[id]][0]+fac[id]*dp[i-fac[id]][1])%mod;
        }
    }
    int _;scanf("%d",&_);
    while(_--){
        scanf("%d",&n);
        printf("%lld\n",(dp[n][0]+dp[n][1])%mod);
    }
    return 0;
}

posted @ 2021-08-16 16:07  hunxuewangzi  阅读(130)  评论(0编辑  收藏  举报