CodeForces 126D

博客解析了CodeForces 126D题目,该题目涉及斐波那契数列和动态规划。通过求解不超过10^18的斐波那契数并存储,利用动态规划方法计算给定数字的不同斐波那契分解方式数量。文章讨论了状态转移方程和初始状态的设定,并分享了代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       这道题表面上是说斐波那契数列,看似是一道找规律的数学题,而实际上却是一道DP题。

       大体思路:题目输入的数字很大,乍一看,好像需要求出几千位斐波那契数,实际上,只要求出87个斐波那契数就足够了。这也是这道题的第一步,求出小于等于10^18的斐波那契数,并保存在fib数组中。fib数组从1开始存储,则每个斐波那契数的下标对应它们在斐波那契数列中的位置。然后,从最大斐波那契数开始,找出一个组成n的一组斐波那契数的序号,并保存在seq数组中(详见代码)。用sort从小到大对seq排序,使得数组中的斐波那契数的下标从小到大排列,与dp数组的第一维下标对应。然后开始标准的动态规划,其中dp[i][1]表示拆分下标为seq[i]的斐波那契数时的情况数,dp[i][0]表示不拆分下标为seq[i]的斐波那契数时的情况数。初始状态,为dp[0][0]=1,dp[0][1]=(seq[0]-1)/2;状态转移方程为dp[i][0]=dp[i-1][0]+do[i-1][1],dp[i][1]=dp[i-1][0]*((seq[i]-seq[i-1]-1)/2)+dp[i-1][1]*((seq[i]-seq[i-1])/2)。要明白这个初始状态和状态转移方程,那就要明白斐波那契数列中第i个斐波那契数有几种替代方案,答案是(i-1)/2,想明白这个,上面的式子就好理解了。

       补充:这是我第一次在CF上提交代码,发现要把DEV中的“system(“PAUSE”);”去掉,否则会WA。此外大家还可以参考一下几篇大神的博文:2014工大校赛题目以及解codeforces 126D Fibonacci Sums 递推 DPCodeforces 126D Fibonacci Sums 求n由任意的Sum(fib)的方法数 dp


代码(GUN C++):

#include <iostream>
#include <algorithm>
#include <cstdio> 

#define MAX 90
using namespace std; 

__int64 fib[MAX],dp[MAX][2];    //dp[i][0]表示fib[seq[i]]不被拆分,dp[i][1]表示fib[seq[i]]被拆分 
int seq[MAX];

void init()
{
    int i; 
    fib[1]=1;
    fib[2]=2;
    for(i=3;i<MAX;i++) fib[i]=fib[i-1]+fib[i-2];
    //for(i=1;i<MAX;i++) cout<<fib[i]<<'\t';
}

int main()
{
    int i,t,c;
    __int64 n;
    init();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%I64d",&n);
        c=0;
        for(i=MAX-1;i>0&&n!=0;i--)
        {
            if(fib[i]<=n)
            {
               seq[c++]=i;
               n-=fib[i];          
            }                 
        }        
        sort(seq,seq+c);
        //for(i=0;i<c;i++) cout<<seq[i]<<endl;
        dp[0][0]=1;
        dp[0][1]=(seq[0]-1)/2;
        for(i=1;i<c;i++)
        {
            dp[i][0]=dp[i-1][0]+dp[i-1][1];
            dp[i][1]=dp[i-1][0]*((seq[i]-seq[i-1]-1)/2)+dp[i-1][1]*((seq[i]-seq[i-1])/2);            
        }
        printf("%I64d\n",dp[c-1][0]+dp[c-1][1]);       
    }       
    //system("PAUSE");   提交CF时要注释掉                             
    return 0;
}


题目( http://codeforces.com/problemset/problem/126/D):

D. Fibonacci Sums
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Fibonacci numbers have the following form:

F1 = 1, 
F2 = 2, 
Fi = Fi - 1 + Fi - 2, i > 2.

Let's consider some non-empty set S = {s1, s2, ..., sk}, consisting of different Fibonacci numbers. Let's find the sum of values of this set's elements:

Let's call the set S a number n's decomposition into Fibonacci sum.

It's easy to see that several numbers have several decompositions into Fibonacci sum. For example, for 13 we have 13, 5 + 8, 2 + 3 + 8 — three decompositions, and for 163 + 13, 1 + 2 + 13, 3 + 5 + 8, 1 + 2 + 5 + 8 — four decompositions.

By the given number n determine the number of its possible different decompositions into Fibonacci sum.

Input

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

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

Please do not use the %lld specificator to read or write 64-bit integers in C++. It is preferred to use the cincout streams or the%I64d specificator.

Output

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

Sample test(s)
input
2
13
16
output
3
4
Note

Two decompositions are different if there exists a number that is contained in the first decomposition, but is not contained in the second one. Decompositions that differ only in the order of summands are considered equal.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值