zoukankan      html  css  js  c++  java
  • cdoj 斐波那契进制

    //昨天在姜神的提醒下发现这种方法可以解决升级版的 非升级版直接01背包就好

    //这题脑洞开得真是够大

    解:大概要先把数分解成斐波拉契进制,x=f1*(0或1)+f2*(0或1)+...+fn*(0或1) f1表示第一个斐波拉契数字(和二进制分解很像 但是这里要分解成斐波拉契进制)

    然后如果一个数分解后某三位位上为100 那么可以将其拆分为011(再拆01011 0101011)

    于是有dp[i][0]代表某一位不拆 dp[i][1]代表某一位拆a[i]代表第i个1后面有多少0,于是

    dp[i][0] += dp[i - 1][0] + dp[i - 1][1];
    dp[i][1] += dp[i - 1][0] * (a[i] / 2) + dp[i - 1][1] * ((a[i] + 1) / 2);

    //那个a[i]/2自己画出来看看就知道了 很显然的

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<queue>
     8 #include<vector>
     9 #include<map>
    10 #include<stack>
    11 #include<string>
    12 
    13 using namespace std;
    14 
    15 long long T;
    16 long long f[100];
    17 long long dp[100][2];
    18 long long a[100];
    19 long long cnt;
    20 
    21 void get_a(long long x){
    22     long long e[100];
    23     memset(e,0,sizeof(e));
    24     for (long long i=90;i>=1;i--){
    25             if (x>=f[i]){
    26                     e[i]=1;
    27                     x-=f[i];
    28             }
    29     }
    30     long long tmp=0;
    31     cnt=0;
    32     memset(a,0,sizeof(a));
    33     for (long long i=1;i<=90;i++){
    34             if (e[i]==1){
    35                     a[++cnt]=tmp;
    36                     tmp=0;
    37             }
    38             else{
    39                     tmp++;
    40             }
    41     }
    42 }
    43 
    44 
    45 int main(){
    46     f[0]=1;
    47     f[1]=1;
    48     for (long long i=2;i<=90;i++) f[i]=f[i-1]+f[i-2];
    49     scanf("%lld",&T);
    50     for (long long cas=0;cas<T;cas++){
    51             long long x;
    52             scanf("%lld",&x);
    53             get_a(x);
    54             memset(dp,0,sizeof(dp));
    55             dp[1][0]=1;
    56             dp[1][1]=a[1]/2;
    57             for (long long  i=2;i<=cnt;i++){
    58                     dp[i][0]=dp[i-1][0]+dp[i-1][1];
    59                     dp[i][1]=dp[i-1][0]*(a[i]/2)+dp[i-1][1]*((a[i]+1)/2);
    60             }
    61             printf("%lld
    ",dp[cnt][0]+dp[cnt][1]);
    62     }
    63     return 0;
    64 }
    65 /*
    66 6
    67 1
    68 2
    69 3
    70 4
    71 5
    72 13
    73 */
  • 相关阅读:
    [java]转:String Date Calendar之间的转换
    ExtJs在页面上window再调用Window的事件处理
    java oracle clob string 大字符串存储【转】
    解决linux系统启动之:unexpected inconsistency:RUN fsck
    线程封闭之栈封闭和ThreadLocal
    Java线程状态和关闭线程的正确姿势
    指令重排序和内存屏障
    浅谈Java内存模型以及交互
    Redis分布式锁的一点小理解
    使用原生Ajax进行用户名重复的检验
  • 原文地址:https://www.cnblogs.com/baby-mouse/p/4502233.html
Copyright © 2011-2022 走看看