【Preface Numbering】羅馬數字
【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】羅馬數字