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;
}
不摆烂了,写题