• 2013多校第四场 F题 ZZ’s Fibonacci Problem


    题意:

      给一个数字x, x<=1e18, 求其分解成数个fib数相加的方案总数.其中fib数不能重复.

    解题思路:

      首先一个结论: 任意一个数,都能被分解成 数个fib数相加的形式.

      另外, 在区间 [1,1e18]总共有 88个fib数.

      对于一个数 x, 我们用一个长度为88的01序列来唯一表示.当前位为1则表示取,否则不取

      例如 8: 00000100...0      2: 00100...0    3: 0110...0  从高位到低位.    

      根据 fib_i =  fib_i-1 + fib_i-2 .

      对于一个序列   001,   其能够被  110 替换. 我们可以总结出. 当前位为1,若其前面有两个0,则可被替换.

    2个0替换一个1, 如此连续. 则若 i为1,其后面有cnt个0, 则其方案数为 cnt/2   (计算机整除,2位为1方案)

      另外我们用一个数组来表示状态:

        dp( i, j ) , 表示第 a[i]位为1时, j = 0,表示不取, j = 1表示取的 方案数.

      j = 1 若当前位取, 则只有中方案, 则其可能是由前一位取或者不取而来.所以有:

        dp( i, 1 ) = dp( i-1, 0 ) + dp( i-1, 1 )

      j= 0 若当前位不取, 

        当其为 前一位取而来时, i前面则有  bi - bi-1 个空格, 所以方案数是  ( b_i - b_(i-1) )/2

          dp( i, j ) = dp( i-1, 0 ) * ( ( b_i - b_(i-1) )/2  )  //注意整除.

        当其为 前一位不取而来时,则i前面的0位增加一个,总数为  b_i - b_(i-1) + 1,所以方案数是 (b_i-b_(i-1)+1)/2

          dp( i, j ) = dp( i-1, 1 ) *( (b_i - b_(i-1) + 1) /2 ) 

    View Code
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    typedef unsigned long long LL;
    const LL inf = (LL)(1e18);
    LL f[100], dp[100][2];
    
    int b[100], cnt;
    
    void init(){
        f[0] = f[1] = 1;
        for(int i = 2; i <= 100; i++){
            f[i] = f[i-1] + f[i-2];
            if( f[i] > inf ){ cnt = i; break; }     
        }
    }
    int main(){
        init(); 
        int T;
        while(scanf("%d", &T)!=EOF){
        while( T-- ){
            LL x;
            int N = 0;;    
            scanf("%lld", &x);
            for(int k = cnt-1; k >= 0; k--)         
                if( x >= f[k] ) b[N++]=k,x-=f[k];
            reverse( b, b+N );
            dp[0][1] = 1;
            dp[0][0] = (b[0]-1)/2;
            for(int i = 1; i < N; i++){
                dp[i][1] = dp[i-1][0] + dp[i-1][1];
                dp[i][0] = dp[i-1][0]*((b[i]-b[i-1])/2) + dp[i-1][1]*((b[i]-b[i-1]-1)/2);
            }
            printf("%lld\n", dp[N-1][0] + dp[N-1][1] );    
        }
        }    
        return 0;
    }
  • 相关阅读:
    P2015 二叉苹果树(树形DP)
    Treats for the Cows (区间DP)
    You Are the One(区间DP 好题)
    Palindrome subsequence (区间DP)
    Cutting Sticks(区间DP)
    L2-013 红色警报 (dfs判断图连通性)
    L2-001 紧急救援 (dijkstra+dfs回溯路径)
    多线程 -- JMM、volatile关键字、内存屏障、happens-before原则、缓存一致性
    多线程 -- 各种锁的概念
    Spring Boot 学习笔记(十六)启动原理、运行流程、自动配置原理
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/3049815.html
Copyright © 2020-2023  润新知