[noip2000]进制转换

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

把 N 反复 divmod 负基数,余数为负时借一位(商 +1、余数 +R)规范化到 [0,R),低位到高位收集后反转即为答案。

OJ: roj

题目 ID: 3500

难度:普及-

标签:进制转换数学模拟

创建: 2026-10-02 03:23

更新: 2026-10-06 12:08

题目描述

给定十进制数 NN(∣N∣≤32767|N| \le 32767)和负进制基数 −R-R(2≤R≤202 \le R \le 20),把 NN 转换为该负进制下的表示。数码超过 99 时用 A…J 表示 1010…1919。

输入每行两个整数 NN 和 −R-R;输出格式为 N=数码串(base-R)。

样例:

text
30000 -2
-20000 -2
28800 -16
-25000 -16

对应输出 30000=11011010101110000(base-2) 等。

思路

从低位向高位逐次做除法取余。C++ 的 % 向零截断,余数可能为负;若余数 r<0r<0,则给商加 11、余数加上 RR(即 r -= base,因为 base 为负),把数码规范化到 [0,R)[0,R)。低位收集完后反转即可。N=0N=0 时直接输出 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 03:23
# update_at: 2026-10-02 03:23

import sys

DIGITS = "0123456789ABCDEFGHIJ"  # 数码 0..19;基数的绝对值不超过 20,超过 9 的用 A..J


def to_negative_base(value: int, base: int) -> str:
    """把十进制 value 写成基数 base(base < 0)下的数码串,高位在前。"""
    if value == 0:
        return "0"
    chars: list[str] = []
    while value:
        value, digit = divmod(value, base)  # Python 向下取整:digit 落在 (base, 0]
        if digit < 0:                       # 借一位,把负数码补成正数码 [0, |base|)
            digit -= base
            value += 1
        chars.append(DIGITS[digit])
    return "".join(reversed(chars))


def solve() -> None:
    data = iter(map(int, sys.stdin.buffer.read().split()))
    out: list[str] = []

    for value, neg_base in zip(data, data):  # 同一行两个数:十进制数 N 与基数 -R
        digits = to_negative_base(value, neg_base)
        out.append(f"{value}={digits}(base{neg_base})")  # 基数按输入原样输出,故带负号

    print("\n".join(out))


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 12:08
 * update_at: 2026-10-06 12:08
 */
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

typedef long long ll;

const char DIGITS[] = "0123456789ABCDEFGHIJ"; // 数码 0..19,超过 9 用 A..J

// 把十进制 v 转成以 base(base < 0)为基数的数码串,高位在前
string to_negative_base(ll v, ll base) {
    if (v == 0) return "0";
    string s;
    while (v != 0) {
        ll q = v / base;   // C++ 向零截断
        ll r = v % base;   // 余数符号跟随被除数,可能为负
        if (r < 0) {       // 借一位:商 +1,余数加上 |base|
            r -= base;     // base 为负,减 base 等价于加 |base|
            q += 1;
        }
        s.push_back(DIGITS[r]);
        v = q;
    }
    reverse(s.begin(), s.end());
    return s;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n, negR;
    while (cin >> n >> negR) {
        string digits = to_negative_base(n, negR);
        cout << n << "=" << digits << "(base" << negR << ")\n";
    }
    return 0;
}