数字转换错误

GitHub跳转原题关系图返回列表

把二进制串逐位翻转、三进制串逐位换成另一个数字,各自枚举候选值,两个集合的交集就是唯一的 N。

OJ: roj

题目 ID: 8007

难度:普及-

标签:进制枚举模拟python

创建: 2026-10-02 16:22

更新: 2026-10-06 16:42

题目描述

毛毛把正整数 NN(N⩽109N \leqslant 10^9)转成二进制和三进制时各写错了一个数字(不会多写少写)。给定她写下的两个串,求 NN。

输入第一行是二进制串,第二行是三进制串,输出 NN 的十进制值。样例输入 1010 / 212,样例输出 14,题目保证解唯一。

思路

把二进制串逐位翻转、三进制串逐位换成另一个数字,各自枚举出候选值集合;答案必同时落在两个集合里,取交集即唯一解。注意首位也可能写错,前导 0 不影响数值。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-02 16:23
# update_at: 2026-10-02 16:23

import sys


def candidates(digits: str, base: int) -> set[int]:
    """把写错的表示按位逐一翻成其他数字,收集所有候选值。

    题目保证恰好错了一个数字:真实表示与写下的表示只有一个数位不同,
    所以候选项 = 每一位取遍其余数字后的所有值(含前导 0,不影响数值)。
    """
    return {
        int(digits[:i] + d + digits[i + 1:], base)
        for i in range(len(digits))
        for d in map(str, range(base))
        if d != int(digits[i])
    }


def solve() -> None:
    two, three = sys.stdin.read().split()
    # 唯一解 = 两个候选集合的唯一交点:既可能来自二进制的修正,也可能来自三进制的修正
    (ans,) = candidates(two, 2) & candidates(three, 3)
    print(ans)


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-06 16:42
 * update_at: 2026-10-06 16:42
 */
#include <iostream>
#include <set>
#include <string>
using namespace std;

typedef long long ll;

string binary_text;  // 毛毛写错的二进制表示
string ternary_text; // 毛毛写错的三进制表示
set<ll> binary_candidates; // 把二进制表示逐位改正后能得到的全部数值

// 把 base 进制的字符串转成十进制数值
ll to_value(const string &s, int base) {
    ll len = s.size();
    ll value = 0;
    for (ll i = 0; i < len; i++) {
        value = value * base + (s[i] - '0');
    }
    return value;
}

int main() {
    cin >> binary_text >> ternary_text;

    ll binary_len = binary_text.size();
    ll ternary_len = ternary_text.size();

    // 二进制只可能是某一位写反,逐位翻转得到候选值(含前导 0 的情况)
    for (ll i = 0; i < binary_len; i++) {
        string fixed = binary_text;
        fixed[i] = (fixed[i] == '0' ? '1' : '0');
        binary_candidates.insert(to_value(fixed, 2));
    }

    // 三进制某一位写成了另外的两个数字之一,逐位换成其余数字
    // 答案必须在两个候选集合的交集中,且题目保证解唯一
    for (ll i = 0; i < ternary_len; i++) {
        for (int d = 0; d < 3; d++) {
            if (d == ternary_text[i] - '0') {
                continue;
            }
            string fixed = ternary_text;
            fixed[i] = '0' + d;
            ll value = to_value(fixed, 3);
            if (binary_candidates.count(value)) {
                cout << value << endl;
                return 0;
            }
        }
    }

    return 0;
}