计蒜课:整数转换成罗马数字

来源:互联网 发布:太阳神三国杀源码教程 编辑:程序博客网 时间:2024/05/17 01:32

题目

题目链接:整数转换成罗马数字 - 题库 - 计蒜课

1000ms,65536K

给定一个整数 num,将整数转换成罗马数字。
如 1, 2, 3, 4, 5 对应的罗马数字分别为I,II,III,IV,V等,更详细的说明见此 链接。

输入格式

第一行输入一个整数 num(1≤num≤3999)。

输出格式

输出 num 对应的罗马数字。

样例输入

123

样例输出

CXXIII

分析

知识准备

罗马数字_百度百科#记数方法

M D C L X V I 1000 500 100 50 10 5 1

1. 相同的数字连写、所表示的数等于这些数字相加得到的数、如:Ⅲ=3;
2. 小的数字在大的数字的右边、所表示的数等于这些数字相加得到的数、 如:Ⅷ=8、Ⅻ=12;
3. 小的数字(限于 I、X 和 C)在大的数字的左边、所表示的数等于大数减小数得到的数、如:Ⅳ=4、Ⅸ=9;
4. 正常使用时、连写的数字重复不得超过三次

基本思路

要将一个整数num(1≤num≤3999)转成罗马数字,首先我们可以对它进行分解:

进制数 M D C L X V I 数值 1000 500 100 50 10 5 1 数值表示 R0 R1 R2 R3 R4 R5 R6 个数 a0 a1 a2 a3 a4 a5 a6

num=aiRii=06
其中
ai=(numajRj)/Rij=0i1
上式的除法为整数整除。这里的分解是从大进制到小进制分解。一般情况下,按第1,2条规则,ai为多少,对应的罗马字符就有多少个;但由于第3,4条规则的限制,所以我们还需要对ai进行修正以及进制数位置进行修正

观察发现

根据上面的分解公式可知:
1. 对于进制为D(500), L(50), V(5)来说,0≤ai≤1,因为如果超过1,就会向前进位;
对于M(1000), C(100), X(10), I(1)l来说,0≤ai≤4,因为如果超过4,就会向前进位;
2. 当一个数某部分需要用到进制相减来表示时,可以相减的两个进制数距离不会超过2个进制距离。否则,这个数一定可以分成出中间的进制,可以用枚举去简单验证;
3. 被减的进制数一定是I(1), X(10), C(100)

特殊情况处理

特殊情况主要发生在要进行进制相减导致进制数位置的变化,有两类这样的问题:
1. 相邻两个进制相减,比如 4:IV,允许我记为“4”问题
2. 相隔1个进制相减,比如 9:IX,记为“9”问题,这种情况相减的时候需要向前借位,高位需要减1。

有更好的算法,欢迎留言联系^_^

实现

我是用c语言实现的(事实上文件保存为c++)

#include <stdio.h>int main(int argc, char const *argv[]) {    char RomanSym[7] = {'M', 'D', 'C', 'L', 'X', 'V', 'I'};    int  RomanNum[7] = {1000, 500, 100, 50, 10, 5, 1};    int  a = 0;    int  k[7] = {0};    char output[100];  // 将翻译成的罗马数字字符串输出到output    scanf("%d", &a);    for (int i = 0; i < 7; i++) {        k[i] = a / RomanNum[i];        a -= k[i] * RomanNum[i];    }    a = 0;  // 重新利用a,作为数组下标    for (int i = 6; i >= 0; i--) {        // 逆序        if (k[i] == 4 && k[i-1] == 0) {            // "4"问题            output[a++] = RomanSym[i-1];            output[a++] = RomanSym[i];        } else if (k[i] == 4 && k[i-1] == 1) {            // "9"问题            k[i-1]--; // 向前借位需要减1            output[a++] = RomanSym[i-2];            output[a++] = RomanSym[i];        } else {            // 其他情况循环输出即可            for (int j = 0; j < k[i]; j++) {                output[a++] = RomanSym[i];            }        }    }    // 逆序输出    for (int i = a - 1; i >= 0; i--) {        putchar(output[i]);    }    putchar('\n');    return 0;}
原创粉丝点击