2465 - 序言页码
一类书的序言是以罗马数字标页码的。传统罗马数字用单个字母表示特定的数值,一下是标准数字表:
I 1 L 50 M 1000
V 5 C 100
X 10 D
500
<span>最多3个可以表示为10n的数字(I,X,C,M)可以连续放在一起,表示它们的和: </span>
<span>III=3 <br />
CCC=300
可表示为5x10n的字符(V,L,D)从不连续出现。
<span>除了下一个规则,一般来说,字符以递减的顺序接连出现: </span>
<span>CCLXVIII = 100+100+50+10+5+1+1+1 = 268 <br />
有时,一个可表示为10^n的数出现在一个比它大的数前(I在V或X前面,X在L或C前面,等等)。在这种情况下,数值等于后面的那个数减去前面的那个数:
<span>IV = 4 <br />
IX = 9
XL = 40
像XD,
IC, 和XM这样的表达是非法的,因为前面的数比后面的数小太多。对于XD(490的错误表达),可以写成 CDXC;
对于IC(99的错误表达),可以写成XCIX; 对于XM(990的错误表达),可以写成CMXC。
<span>给定N(1 <= N < 3,500),
序言的页码数,请统计在第1页到第N也中,有几个I出现,几个V出现,等等 (从小到大的顺序)。不要输出并没有出现过的字符。
<span>比如N = 5, 那么页码数为: I, II, III, IV, V.
总共有7个I出现,2个V出现。
题目输入
一个整数N。
题目输出
每行一个字符和一个数字k,表示这个字符出现了k次。字符必须按数字表中的递增顺序输出。
输入/输出样例
题目输入
5
题目输出
I 7 V 2
C++解答
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; int aa[7]={0}; char* a[4][10]; char b[7]={'I','V','X','L','C','D','M'}; void doo(int as) { int an=0; int n=0; while(as!=0) { if (as%10!=0) { for (int i=0;i<strlen(a[n][as%10]);i++) switch (a[n][as%10][i]) { case 'I':{aa[0]++;break;} case 'V':{aa[1]++;break;} case 'X':{aa[2]++;break;} case 'L':{aa[3]++;break;} case 'C':{aa[4]++;break;} case 'D':{aa[5]++;break;} case 'M':{aa[6]++;break;} } } as=as/10; n++; } } int main() { a[0][1]="I";a[0][2]="II";a[0][3]="III";a[0][4]="IV";a[0][5]="V";a[0][6]="VI";a[0][7]="VII";a[0][8]="VIII";a[0][9]="IX"; a[1][1]="X";a[1][2]="XX";a[1][3]="XXX";a[1][4]="XL";a[1][5]="L";a[1][6]="LX";a[1][7]="LXX";a[1][8]="LXXX";a[1][9]="XC"; a[2][1]="C";a[2][2]="CC";a[2][3]="CCC";a[2][4]="CD";a[2][5]="D";a[2][6]="DC";a[2][7]="DCC";a[2][8]="DCCC";a[2][9]="CM"; a[3][1]="M";a[3][2]="MM";a[3][3]="MMM"; int n; while(scanf("%d",&n)!=EOF) { memset(aa,0,sizeof(aa)); for (int i=1;i<=n;i++) doo(i); for (int i=0;i<7;i++) if (aa[i]) printf("%c %d\n",b[i],aa[i]); } return 0; }