ZZ’s Fibonacci Problem

Describe:

ZZ is a big fan of Fibonacci numbers, and she pays lots of attention on Fibonacci numbers, Fibonacci numbers have the following form: F(1) = 1, F(2) =2, F(i) = F(i-1) + F(i-2), i > 2.  ZZ is a so clever girl, she found some interested things, a non-empty set S = { s1,s2……sk }, consisting of different Fibonacci numbers, the sum of this set’s elements call the set S a number n’s decomposition into Fibonacci sum. It’s easy to see that the numbers have several decompositions into Fibonacci sum, for example, for 13 we have 13, 5 + 8, 2 + 3 + 8 three decomposition, and for 16,3 +13, 1 + 2 +13 , 3 + 5 + 8, 1 + 2 + 5 + 8 --- four decompositions . ZZ is so happy of find this, but what's a pity,  ZZ don’t know how to find the number of the possible different decompositions into Fibonacci sum if give a number n ? Can you help her? 

Input:

The first line contains an integer t — the number of tests (1≤t≤10). Each of the following t lines contains one test.

Each test is an integer n (1≤n≤10).

Output

For each input data test print a single number on a single line — the answer to the problem.

Sample:

Input:

Output:

2

13

16

3

4

 

解题思路:

首先,明确一点,任何数都可以由一个或多个斐波那契数组成;

由于斐波那契数的级数是非常大的,事实上到达__int64的斐波那契数将近在88个左右,所以预处理一下。

首先我们要先找出这样一种方案:方案中的最大的非波那且数  最大,为了保证在后面DP的时候不会漏掉一些情况。我们用一个特殊的二进制来表示我们刚刚得到的方案,

比如1000000100000001,二进制位为表示取了这个非波那且数(从左往右依次增大),那么一个1可以表示成左边两个1001 ->110,那么某个1的表示方法就是cnt/2 ,

 cnt为这个1与前面的1之间0的个数,所以总的方案数可以利用乘法原理从左往右递推过来,每个要么取,要么不取,取的话就只有一种方法,

不取的话就可以表示成中间若干个1的和,分两种情况转移即可.

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 int t;
 9 long long n;
10 long long fib[90];
11 long long b[90];
12 long long dp[90][2];
13 
14 int main()
15 {
16     fib[0]=1;
17     fib[1]=1;
18     for(int i=2; i<=88; i++)
19         fib[i]=fib[i-1]+fib[i-2];
20     while(scanf("%d",&t)!=EOF)
21     {
22         while(t--)
23         {
24             scanf("%lld",&n);
25             int k=1;
26             memset(b,0,sizeof(b));
27             for(int i=88; i>=1; i--)
28             {
29                 if(n>=fib[i])
30                 {
31                     n-=fib[i];
32                     b[k++]=i;
33                 }
34             }
35             reverse(b+1,b+k);
36             dp[1][1]=1;
37             dp[1][0]=(b[1]-1)/2;
38             for(int i=2; i<k; i++)
39             {
40                 dp[i][1]=dp[i-1][0]+dp[i-1][1];
41                 dp[i][0]=(dp[i-1][0])*((b[i]-b[i-1])/2)+dp[i-1][1]*((b[i]-b[i-1]-1)/2);
42             }
43             printf("%lld\n",dp[k-1][0]+dp[k-1][1]);
44         }
45 
46     }
47     return 0;
48 }
View Code

 

 

posted @ 2013-05-21 23:08  1002liu  阅读(141)  评论(0编辑  收藏  举报