1. 程式人生 > >【Preface Numbering】羅馬數字

【Preface Numbering】羅馬數字

let 一個數 單個 大量 羅馬 define string LV bit

【Problem description】

  一類書的序言是以羅馬數字標頁碼的。傳統羅馬數字用單個字母表示特定的數值,一下是標準數字表:

  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
  有時,一個可表示為10^n的數出現在一個比它大的數前(I在V或X前面,X在L或C前面,等等)。在這種情況下,數值等於後面的那個數減去前面的那個數:

  IV = 4
  IX = 9
  XL = 40
  像XD, IC, 和XM這樣的表達是非法的,因為前面的數比後面的數小太多。對於XD(490的錯誤表達),可以寫成 CDXC; 對於IC(99的錯誤表達),可以寫成XCIX; 對於XM(990的錯誤表達),可以寫成CMXC。

  給定N(1 <= N < 3,500), 序言的頁碼數,請統計在第1頁到第N也中,有幾個I出現,幾個V出現,等等 (從小到大的順序)。不要輸出並沒有出現過的字符。

  比如N = 5, 那麽頁碼數為: I, II, III, IV, V. 總共有7個I出現,2個V出現。

【Input format】  

一個整數N。

【Output format】

每行一個字符和一個數字k,表示這個字符出現了k次。字符必須按數字表中的遞增順序輸出。

【Algorithm design】

Simple enumeration

【Problem analysis】

優化前:

就是一個理解和順向模擬的題目

對於1到n的每一個數搞一下就行了

采取的順序是從整到零

由最左向右逐漸推進即可

優化後:

針對大量的重復運算

按位數分三種情況處理即可

【Source code】

#include <bits/stdc++.h>

#define F(i,j,k) for(int i=j;i<=k;i++)

#define D(i,j,k) for(int i=j;i>=k;i--)

using namespace std;

string let="IVXLCDM";

int cnt,cnt_let[7];

void input()

{

cin>>cnt;

return;

}

void work()

{

F(turn,1,cnt)

{

int num=turn;

int lvl_chk=0;

while(num)

{

int num_chk=num%10;

if(num_chk<=3)

cnt_let[lvl_chk]+=num_chk;

else if(num_chk<=8)

{

cnt_let[lvl_chk]+=abs(num_chk-5);

cnt_let[lvl_chk+1]+=1;

}

else

{

cnt_let[lvl_chk]+=1;

cnt_let[lvl_chk+2]+=1;

}

lvl_chk+=2;

num/=10;

}

}

return;

}

void output()

{

F(i,0,6)

if(cnt_let[i])cout<<let[i]<<" "<<cnt_let[i]<<endl;

return;

}

int main()

{

freopen("preface.in","r",stdin);

freopen("preface.out","w",stdout);

input();

work();

output();

return 0;

}

【Preface Numbering】羅馬數字