C++ 代码
#include <iostream>
using namespace std;
//下面的列表分别为个,十,百,千位为1~9的罗马数字的表示方法
//可以发现这个序列存在一定的规律
//每一行只需要三个字母(最小字母,中等字母,最大字母),并且这三个字母的出现次数是相同的
//I II III IV V VI VII VIII IX 第一行的最小字母为I,中等字母为V,最大字母为X,
//X XX XXX XL L LX LXX LXXX XC 最小为X,中等为L,最大为C
//C CC CCC CD D DC DCC DCCC CM 最小为C,中等为D,最大为M
//M MM MMM
char ch[] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'};
//ans存的是罗马字母总的出现次数
int ans[7];
//cnt数组存的是数字1~9分别所需要的最小、中等、最大字母的个数
int cnt[10][3] = {
//比如下方的
//{1, 0, 0}表示的是1(数组cnt的行下标)需要最小字母1个,中等0个,最大0个
{0, 0, 0},{1, 0, 0},{2, 0, 0},{3, 0, 0},{1, 1, 0},{0, 1, 0},{1, 1, 0},{2, 1, 0},
{3, 1, 0},{1, 0, 1}
};
//分解数字的每一位,把需要的罗马数字加到ans数组中去
void add(int x){
//d为偏移量,为什么我们需要一个偏移量?
//比如数字11,我们可以把他分解为个位上的1 + 十位上的1
//那么当我们处理完个位上的1之后,我们需要将我们的最小、中等、字母更新
//处理个位时,这三个字母分别为'I' 'V' 'X',处理百位时应该为'X' 'L' 'C'......以此类推
//我们发现每个字母的下标偏移量为2
int d = 0;
while (x){
for (int i = 0; i < 3; ++i){
//分别计算最小、中等、最大字母的出现次数
ans[i + d] += cnt[x % 10][i];
}
d += 2;
x /= 10;
}
}
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; ++i)
add(i);
for (int i = 0; i < 7; ++i)
if (ans[i]) printf("%c %d\n",ch[i],ans[i]);
return 0;
}
数组越界还能AC,真奇怪
在第35行后加入
一行,在N=1000时会发现多输出了7和8
明明越界了
666