2465 - 序言页码

通过次数

0

提交次数

0

时间限制 : 1 秒 内存限制 : 128 MB

一类书的序言是以罗马数字标页码的。传统罗马数字用单个字母表示特定的数值,一下是标准数字表:

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 &lt;= N &lt; 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;
}