USACO 2.2 Preface Numbering 【实质是分治思想】

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

I 1 V 5 X 10 L 50 C 100 D 500 M 1000

最多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

一个数 用罗马数字来表示 有且仅有一种 而且不能复合嵌套使用(比如I是1 X是10 有人可能要说 IXL就能表示50-10-1 但是IXL绝对不能用来表达39 ) (那么39用什么来表示呢 XXXIX是唯一 而且正确的选择- -)

像XD, IC, 和XM这样的表达是非法的,因为前面的数比后面的数小太多。对于XD(490的错误表达),可以写成 CDXC; 对于IC(99的错误表达),可以写成XCIX; 对于XM(990的错误表达),可以写成CMXC。 90 写成 XC 而不是 LXL, 因为 L 后面的 X 意味着后继标记是 X 或者更小 (不管怎样,可能吧)(等同于阿拉伯数字 每位 数字分别表示)。

给定N(1 <= N < 3,500), 序言的页码数,请统计在第1页到第N页中,有几个I出现,几个V出现,等等 (从小到大的顺序)。不要输出没有出现过的字符。

比如N = 5, 那么页码数为: I, II, III, IV, V. 总共有7个I出现,2个V出现。

输入输出格式

输入格式:

 

一个整数N。

 

输出格式:

 

每行一个字符和一个数字k,表示这个字符出现了k次。字符必须按数字表中的递增顺序输出。

 

输入输出样例

输入样例#1:
5
输出样例#1:
I 7
V 2
 
 
 
 
 
 
在这里借鉴洛谷Fop_zz同志的思路,好好发扬光大:
1、从一个多位数到具体位上的数字
通过分析,我们可以发现,一个多位数,它各个位上的数字转换成罗马数字后是互不干扰的(到时只需记录循环到了第几位,乘以10就行了),因此我们只需考虑一个个位数,如何把它转换成罗马数字。
2、把9个数字分类(设此时到了第k位(从个位起))
注:I*k 表示 I 或 X 或 C 或 M (以此类推)
1----输出‘I*k’
2~3-----重复输出‘I*k’
4-----输出‘IV*k’
5-----输出‘V*k’
6~8-----输出‘V*k’,再重复输出‘I*k’
9-----输出‘I*k’,再输出‘I*(k+1)’   //例如:9*1=10*1-1*1 ; 9*10=10*10-1*10
其中:6~8 的情况可以先处理掉一个5,再交给 1~3 去处理
3、k 与下标的关系
所有的k+3表示整除10的数;而k表示整除5的数
数组下标(k)    罗马数字    表示的十进制数

4                       I                      1

1                       V                     5

5                       X                     10

2                        L                    50

6                        C                   100

3                        D                     500

7                        M                   1000

 
下面是参考代码
 
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 int n;
 7 int a[8]={0};
 8 void f(int x)
 9 {
10     int t=0;
11     while(x>0)
12     {
13         t++;//相当于k,记录到了第几位,到时候*10^k 
14         int xx=x%10;
15         if(xx==9)
16         {
17             a[t+3]++;   // IX 中的" I "
18             a[t+4]++;   // IX 中的" X "
19         }
20         else 
21         {
22             if(xx>=5)
23             {
24                 a[t]++;   // " V "
25                 xx-=5;                
26             }
27             if(xx==4)
28             {
29                 a[t]++;
30                 a[t+3]++;                
31             }
32             else
33                 a[t+3]+=xx;
34         }
35         x/=10;      // 一位一位剥掉它
36     }
37 }
38 
39 
40 int main()
41 {
42     freopen("preface.in","r",stdin);
43     freopen("preface.out","w",stdout);
44     cin>>n;
45     for(int i=1;i<=n;i++)
46         f(i);
47     if(a[4]) cout<<'I'<<" "<<a[4]<<endl;
48     if(a[1]) cout<<'V'<<" "<<a[1]<<endl;
49     if(a[5]) cout<<'X'<<" "<<a[5]<<endl;
50     if(a[2]) cout<<'L'<<" "<<a[2]<<endl;
51     if(a[6]) cout<<'C'<<" "<<a[6]<<endl;
52     if(a[3]) cout<<'D'<<" "<<a[3]<<endl;
53     if(a[7]) cout<<'M'<<" "<<a[7]<<endl;
54     return 0;
55 }

 

posted @ 2017-07-19 15:37  Captain_fcj  阅读(190)  评论(0编辑  收藏  举报