模拟 - Death to Binary? - POJ 2116

模拟 - Death to Binary? - POJ 2116

题意:

斐 波 那 契 数 列 : 斐波那契数列:

F n = F n − 1 + F n − 2 , F 0 = 1 , F 1 = 2 , n ≥ 2. F_n=F_{n-1}+F_{n-2},F_0=1,F_1=2,n\ge2. Fn=Fn1+Fn2F0=1,F1=2n2.

给 定 一 个 01 串 S , 用 斐 波 那 契 数 列 来 表 示 十 进 制 数 , 给定一个01串S,用斐波那契数列来表示十进制数, 01S

例 如 110100 1 F i b = F 0 + F 3 + F 5 + F 6 = 1 + 5 + 13 + 21 = 40 。 例如1101001_{Fib }= F_0 + F_3 + F_5 + F_6 = 1 + 5 + 13 + 21 = 40。 1101001Fib=F0+F3+F5+F6=1+5+13+21=40

每 个 整 数 都 可 以 以 此 基 数 表 示 , 但 不 一 定 以 唯 一 的 方 式 表 示 。 例 如 40 也 可 以 表 示 为 1000100 1 F i b 。 但 是 , 对 于 任 何 整 数 , 都 有 一 个 不 包 含 两 个 相 邻 数 字 1 的 唯 一 表 示 形 式 我 们 将 此 表 示 形 式 称 为 规 范 。 例 如 , 1000100 1 F i b 是 40 的 标 准 斐 波 那 契 表 示 形 式 。 每个整数都可以以此基数表示,但不一定以唯一的方式表示。\\例如40也可以表示为10001001_{Fib}。\\但是,对于任何整数,都有一个不包含两个相邻数字1的唯一表示形式\\我们将此表示形式称为规范。例如,10001001 _{Fib}是40的标准斐波那契表示形式。 4010001001Fib110001001Fib40

输入:

多 组 测 试 数 据 , 每 组 包 括 共 两 个 01 串 X 和 Y 。 多组测试数据,每组包括共两个01串X和Y。 01XY

输出:

计 算 X + Y 的 斐 波 那 契 表 示 , 以 竖 式 计 算 的 形 式 呈 现 出 来 , 计算X+Y的斐波那契表示,以竖式计算的形式呈现出来, X+Y

X 的 规 范 形 式 + Y 的 规 范 形 式 _ _ _ _ _ _ _ _ _ _ _ _ 答 案 的 规 范 形 式 \qquad X的规范形式\\+ \quad Y的规范形式\\\qquad\_\_\_\_\_\_\_\_\_\_\_\_\\\qquad答案的规范形式 X+Y____________

Sample Input

11101 1101
1 1

Sample Output

   100101
+   10001
  -------
  1001000

   1
+  1
  --
  10

数据范围:

∣ X ∣ , ∣ Y ∣ ≤ 40 |X|,|Y|\le 40 X,Y40


分析:

由 于 X , Y 的 长 度 很 小 , 就 可 以 暴 力 乱 搞 。 由于X,Y的长度很小,就可以暴力乱搞。 XY

如 何 将 一 个 01 串 转 化 为 规 范 形 式 ? 如何将一个01串转化为规范形式? 01

先 将 其 转 化 为 10 进 制 数 V , 再 从 十 进 制 V 转 化 为 规 范 形 式 。 先将其转化为10进制数V,再从十进制V转化为规范形式。 10VV

① 、 转 化 为 10 进 制 数 : 字 符 串 的 第 i 位 是 1 , 就 累 加 上 F i 。 ①、转化为10进制数:字符串的第i位是1,就累加上F_i。 10i1Fi

② 、 转 化 为 规 范 形 式 : 从 大 到 小 枚 举 斐 波 那 契 数 列 的 第 i 项 , 若 V ≥ F i , 就 减 去 F i , 同 时 添 加 一 个 1 , 否 则 添 加 1 个 0 。 ②、转化为规范形式:从大到小枚举斐波那契数列的第i项,若V\ge F_i,就减去F_i,同时添加一个1,否则添加1个0。 iVFiFi110

规 范 形 式 即 不 存 在 连 续 的 1 , 下 说 明 ② 的 操 作 方 法 能 够 保 证 不 出 现 连 续 的 1 。 规范形式即不存在连续的1,下说明②的操作方法能够保证不出现连续的1。 11

因 为 F n = F n − 1 + F n − 2 , n ≥ 2 , 因 为 我 们 是 从 大 到 小 枚 举 的 斐 波 那 契 数 列 的 第 i 项 , 因为F_n=F_{n-1}+F_{n-2},n\ge 2,因为我们是从大到小枚举的斐波那契数列的第i项, Fn=Fn1+Fn2n2i

若 在 第 i − 1 位 和 第 i − 2 位 上 存 在 连 续 的 两 个 1 , 即 相 当 于 在 第 i 位 上 有 一 个 1 , 我 们 会 优 先 减 去 F i , 若在第i-1位和第i-2位上存在连续的两个1,即相当于在第i位上有一个1,我们会优先减去F_i, i1i21i1Fi

之 后 到 第 i − 1 位 时 , 1 就 不 存 在 了 。 之后到第i-1位时,1就不存在了。 i11

注意:

用 空 字 符 串 进 行 操 作 ② 时 , 注 意 结 果 为 0 的 情 况 , 不 能 返 回 空 串 。 用空字符串进行操作②时,注意结果为0的情况,不能返回空串。 0

代码:

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

using namespace std;

const int N=50;

int f[N];
string a,b;

void Init()
{
    f[0]=1, f[1]=2;
    for(int i=2;i<N;i++) f[i]=f[i-1]+f[i-2];
}

string trans(string x,int & vx)
{
    reverse(x.begin(),x.end());
    vx=0;
    int len=x.size();
    for(int i=0;i<len;i++)
        if(x[i]=='1')
            vx+=f[i];
    
    int tmp=vx;
    string res="";
    for(int i=40;i>=0;i--)
    {
        if(tmp-f[i]>=0) 
        {
            tmp-=f[i];
            res+='1';
        }
        else if(res!="") res+='0';
    }
    if(res=="") res="0";
    
    return res;
}

int main()
{
    Init();
    while(cin>>a>>b)
    {
        int va=0, vb=0;
        a=trans(a,va), b=trans(b,vb);
        int la=a.size(), lb=b.size();
        
        int vc=va+vb;
        string ans="";
        for(int i=40;i>=0;i--)
            if(vc-f[i]>=0)
            {
                ans+='1';
                vc-=f[i];
            }
            else if(ans!="") ans+='0';
        if(ans=="") ans="0";

        int len=ans.size();
        for(int i=0;i<=len-la+1;i++) printf(" ");cout<<a<<endl;
        printf("+");
        for(int i=0;i<=len-lb;i++) printf(" ");cout<<b<<endl;
        printf("  ");
        for(int i=0;i<len;i++) printf("-");puts("");
        cout<<"  "<<ans<<endl;
        puts("");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值