描述
一类书的序言是以罗马数字标页码的。传统罗马数字用单个字母表示特定的数值,以下是标准数字表:
I 1 L 50 M 1000 V 5 C 100 X 10 D 500
最多3个同样的可以表示为10n的数字(I,X,C,M)可以连续放在一起,表示它们的和:
III=3 CCC=300
可表示为5x10n的字符(V,L,D)从不连续出现。
除了下一个规则,一般来说,字符以递减的顺序接连出现:
CCLXVIII = 100+100+50+10+5+1+1+1 = 268
有时,一个可表示为10n的数出现在一个比它大1级或2级的数前(I在V或X前面,X在L或C前面,等等)。在这种情况下,数值等于后面的那个数减去前面的那个数:
IV = 4 IX = 9 XL = 40
This compound mark forms a unit and may not be combined to make another compound mark (e.g., IXL is wrong for 39; XXXIX is correct).
像XD, IC, 和XM这样的表达是非法的,因为前面的数比后面的数小太多。对于XD(490的错误表达),可以写成 CDXC; 对于IC(99的错误表达),可以写成XCIX; 对于XM(990的错误表达),可以写成CMXC。 90 is expressed XC and not LXL, since L followed by X connotes that successive marks are X or smaller (probably, anyway).
给定N(1 <= N < 3,500), 序言的页码数,请统计在第1页到第N页中,有几个I出现,几个V出现,等等 (从小到大的顺序)。不要输出并没有出现过的字符。
比如N = 5, 那么页码数为: I, II, III, IV, V. 总共有7个I出现,2个V出现。
格式
PROGRAM NAME: preface
INPUT FORMAT:
(preface.in)
一个整数N。
OUTPUT FORMAT:
(preface.out)
每行一个字符和一个数字k,表示这个字符出现了k次。字符必须按数字表中的递增顺序输出。
SAMPLE INPUT
5
SAMPLE OUTPUT
I 7 V 2
这么简单一道题都不能快速做出来,卡了好久,明明有枚举的方法还非要用数学方法。。。
也可能是开始算法对了,但是忘记处理下标越界和为负数的情况,导致结果一直不对。。。
/*
ID: your_id_here
PROG: preface
LANG: C++
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int nn[3][10]={0,1,2,3,1,0,1,2,3,1,
0,0,0,0,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,0,1};
const int nm[3][10]={0,1,3,6,7,7,8,10,13,14,
0,0,0,0,1,2,3,4,5,5,
0,0,0,0,0,0,0,0,0,1};
int n,num[11],t,t1,t2,tt,tp;//num数组开小了,又是本地对,OJ错...
char ch[8]="IVXLCDM";
int main() {
int i;
freopen("preface.in","r",stdin);
freopen("preface.out","w",stdout);
while(1==scanf("%d",&n)) {
for(i=0;i<8;++i)
num[i]=0;
i=0,tp=1,tt=1,t=n;
while(t) {
t1=t/10;
tt=t%10-1;
if(tt==-1)//可能存在数组越界的问题,所以tt为-1时将其赋为0
tt=0;
//每次计算的时候分为三部分:假设目前数字为abc
//Ⅰ:当前看个位
//①ab(即c前面的数字)个0~9完整出现过 ②1个0~c-1完整出现过 ③n%tp+1(即c后面的数字+1=0+1)个c出现过
//Ⅱ:当前看十位
//①a(即b前面的数字)个0~9完整出现过 ②1个0~b-1完整出现过 ③n%tp+1(即b后面的数字+1=b+1)个b出现过
//Ⅲ:当前看百位
//①0(即a前面的数字)个0~9完整出现过 ②1个0~a-1完整出现过 ③n%tp+1(即b后面的数字+1=a+1)个a出现过
num[i]+=t1*nm[0][9]*tp+nm[0][tt]*tp+(n%tp+1)*nn[0][t%10];
num[i+1]+=t1*nm[1][9]*tp+nm[1][tt]*tp+(n%tp+1)*nn[1][t%10];
num[i+2]+=t1*nm[2][9]*tp+nm[2][tt]*tp+(n%tp+1)*nn[2][t%10];
t=t1;
i+=2;
tp*=10;
}
i=0;
while(num[i]) {
printf("%c %d\n",ch[i],num[i]);
++i;
}
}
return 0;
}