POJ1023 - The Fun Number System 解题报告

POJ1023 - The Fun Number System 解题报告

原题解析

题目的大意为,给定一个长度 k [1, 64] 。
给定一个长度为 k 的字符串 s ,由 p 和 n 组成。
给定一个十进制数 n [-263, 263] 。
求一个二进制数 r ,使得 r 按照一个特殊的计算系统可以算得 n 。

特殊的计算系统

正常来说,将一个二进制数转化为十进制数时,需要对应的每一位 0 或 1 乘以系数,既对应位数 k 的 2k-1 ,再全部相加,形如:

0x11001 = 1 * 25-1 + 1 * 24-1 + 1 * 21-1 = 25

这里特殊的计算系统,在乘以系数时会根据位数 k 对应的字符串中的字符是 p 还是 n 来做出不同的操作。
当对应的字符是 p 时,系数没有特别的变化。
当对应的字符是 n 时,系数还要额外乘以 -1 。
举例:

s = ppnnn
0x11001 = 1 * 25-1 + 1 * 24-1 - 1 * 21-1 = 23

也就是说,这里会提供十进制数 23 ,而我们需要求出原本的 0x11001 。

解题思路

其实解法到这里已经呼之欲出,逆运算就行了。
按照之前的例子,在已知 0x11001 时要计算出 23 (0x10111) 时,会按位进行运算。
像这样运算:

第 1 位,0x11001 ppnnn ,得到 1 。
第 2 位,0x11001 ppnnn ,得到 1 * 2 + 1 = 3 。
第 3 位,0x11001 ppnnn ,得到 3 * 2 = 6 。
第 4 位,0x11001 ppnnn ,得到 6 * 2 = 12 。
第 5 位,0x11001 ppnnn ,得到 12 * 2 - 1 = 23 。

而反过来运算就是:

第 5 位, 23 ppnnn , 23 & 1 = 1 , 0xXXXX1 , (23 + 1) / 2 = 12 。
第 4 位, 12 ppnnn , 12 & 1 = 0 , 0xXXX01 , 12 / 2 = 6 。
第 3 位, 6 ppnnn , 6 & 1 = 0 , 0xXX001 , 6 / 2 = 3 。
第 2 位, 3 ppnnn , 3 & 1 = 1 , 0xX1001 , (3 - 1) / 2 = 1 。
第 1 位, 1 ppnnn , 1 & 1 = 1 , 0x11001 , (1 - 1) / 2 = 0 。

得到 0x11001 。

归纳过程:

  1. 遇 0 得 0,遇 1 得 1 ;
  2. 遇 1 时,遇 p 减 1,遇 n 加 1 ;(因为要除2,所以减 1 可以省略)
  3. 如果最后的结果不是 0 ,则说明原操作不成立,既 Impossible ;

示例代码

#include <stdio.h>
#include <string.h>

struct State
{
    int k;
    char s[65];
    long long n;

    char output[65];
};

void input(State& state);
void calc(State& state);
void output(State& state);

int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        State state;
        input(state);
        calc(state);
        output(state);
    }
    return 0;
}

void input(State& state)
{
    scanf("%d", &(state.k));
    scanf("%s", state.s);
    scanf("%lld", &(state.n));
}

void calc(State& state)
{
    long long n = state.n;

    state.output[state.k] = 0;
    for (int i = state.k - 1; i >= 0; --i)
    {
        if (n & 1)
        {
            if (state.s[i] == 'n')
            {
                n += 1;
            }
            state.output[i] = '1';
        }
        else
        {
            state.output[i] = '0';
        }
        n >>= 1;
    }

    if (n)
    {
        strcpy(state.output, "Impossible");
    }
}

void output(State& state)
{
    printf("%s\n", state.output);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值