一类书的序言是以罗马数字标页码的。传统罗马数字用单个字母表示特定的数值,以下是标准数字表:
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次。字符必须按数字表中的递增顺序输出。
5
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; }