先考虑一个斐波那契数能分成其他斐波那契数的方案,假如f[i]表示第i个斐波那契数,那么只要对他进行拆分,f[i-1]这个数字必定会存在。知道这一点就可以进行递推了。先将数字分成最少项的斐波那契数之和,s[i]表示第i项的数字对应的斐波那契数编号,F[i]表示对不第i项进行拆分,G[i]表示对第i项进行拆分,g[i]表示对编号为i的斐波那契数拆分的话,有多少种方案。那么可以得到递推式:
F[i]=F[i-1]+G[i-1];
G[i]=F[i-1]*(g[s[i]-s[i-1]])+G[i-1]*(g[s[i]-s[i-1]+1]);
代码
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #define N 1000010 5 #define P 100000007 6 using namespace std; 7 long long n,f[N],Q,ans,g[N],F[N],G[N]; 8 int s[N],tot; 9 int i; 10 int main() 11 { 12 f[1]=1; 13 f[2]=2; 14 Q=1000000000; 15 Q=Q*Q; 16 for (i=3;i<=100;i++) 17 { 18 f[i]=f[i-2]+f[i-1]; 19 if (f[i]>Q) break; 20 } 21 g[1]=1; 22 for (i=2;i<=100;i++) 23 if (i%2) 24 g[i]=g[i-1]+1; 25 else 26 g[i]=g[i-1]; 27 for (i=1;i<=100;i++) 28 g[i]--; 29 int test; 30 scanf("%d",&test); 31 while (test) 32 { 33 test--;tot=0; 34 scanf("%I64d",&n); 35 for (i=86;i>=1;i--) 36 if (n-f[i]>=0) 37 { 38 tot++;s[tot]=i; 39 n=n-f[i]; 40 } 41 ans=1; 42 F[tot]=1; 43 G[tot]=g[s[tot]]; 44 for (i=tot-1;i>=1;i--) 45 { 46 F[i]=F[i+1]+G[i+1]; 47 G[i]=F[i+1]*(g[s[i]-s[i+1]])+G[i+1]*(g[s[i]-s[i+1]+1]); 48 } 49 printf("%I64d\n",F[1]+G[1]); 50 } 51 }
时间: 2024-11-25 01:42:47