[关闭]
@RiverHamster 2017-11-18T17:15:13.000000Z 字数 1359 阅读 3144

Luogu P1465 序言页码(罗马数字打表)


楼下的打表不太好理解,来一发好写又好理解的打表方法。

罗马数字的构造方法:

每一位之间没有关系,可以分别处理,直接把千位、百位、十位、个位按顺序放就可以。0直接跳过
例如:123:CXXIII
每一位上的数字的表示方法:
“表示方法”列中以个位为例,1=I,5=V,10=X,n表示这一位上的数字,十位百位以此类推。

类别 表示方法(以个位为例) 示例1 示例2
1~3 n个I 2=II 30=LLL
4 IV 4=IV 400=CD
5~8 V和(n-5)个I 5=V 70=LXX
9 IX 9=IX 900=CM

打表关键代码

s[i][j]表示右数第i位(个位i=1)上的j的表示方法,注意数组赋初值的格式。

  1. string s[5][11]={ //注意每一位上的0都给出空字符串,方便操作
  2. {}, //空出第0行
  3. {"","I","II","III","IV","V","VI","VII","VIII","IX"}, //个位
  4. {"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"}, //十位
  5. {"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"}, //百位
  6. {"","M","MM","MMM"} //千位(打3个就可以满足题目要求)
  7. };

对每一个数进行计数:(uint是unsigned int)

  1. void Calc(int n){
  2. int now=1; //当前的数位
  3. while(n>0){
  4. Count(s[now][n%10]); //将字符串计数
  5. now++,n/=10; //下一位
  6. }
  7. }

完整代码:

  1. #include <cstdio>
  2. #include <string>
  3. #include <iostream>
  4. typedef unsigned int uint;
  5. using namespace std;
  6. string s[5][11]={
  7. {},
  8. {"","I","II","III","IV","V","VI","VII","VIII","IX"},
  9. {"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"},
  10. {"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"},
  11. {"","M","MM","MMM"}
  12. };
  13. string ap="IVXLCDM"; //罗马数字列表,方便输出
  14. int c[300]; //统计数组
  15. void Count(string s){ //将字符串每一位统计
  16. for(uint i=0;i<s.size();i++) c[(uint)s[i]]++;
  17. }
  18. void Calc(int n){
  19. int now=1;
  20. while(n>0){
  21. Count(s[now][n%10]);
  22. now++,n/=10;
  23. }
  24. }
  25. int main(){
  26. int n;
  27. scanf("%d",&n);
  28. for(int i=1;i<=n;i++) Calc(i); //对每一个数字统计
  29. for(uint i=0;i<ap.size();i++){ //按顺序输出
  30. if(c[(uint)ap[i]]>0) //有这个字母
  31. printf("%c %d\n",ap[i],c[(uint)ap[i]]);
  32. }
  33. return 0;
  34. }

讨论板

将鼠标放到这里,点击右边的按钮来批注

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注