题目链接
题目思路
首先一个及其暴力的思路(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
",(dp[n][0]+dp[n][1])%mod);
}
return 0;
}