USACO 2.2.1 Preface Numbering 羅馬數字轉換 preface
相信許多人遇到這道題都暈了,羅馬數字的規則的確太複雜了。想了解羅馬數字的看這裏: 羅馬數字介紹
理解簡單的(題目上3500以內)羅馬數字轉化規則後再看這道題會發現它並不難,就是將1..n的每個十進制阿拉伯數字轉化成相應的羅馬數字串,然後統計每個字母出現的次數就可以了。
關鍵在於轉化阿拉伯數字(其實較大的羅馬數字轉化很複雜,而題中3500以內的羅馬數字轉化還是比較簡單的,所以只討論如何轉化3500以內的羅馬數字)。
轉化有以下規則: 1、數較大部分在前,較小部分在後 2、表示10整倍數的字母(I X C M)最多可以累加三次 3、要累加4次的數應該將比該數的字母稍大的表示5整倍數或是10的整倍數的字母在後,累加的字母在前(例如IV XL CD CM)
瞭解以上規則後發現並不需要實際“轉化”出羅馬數字,而只用統計每個字母出現的次數。可以用遞歸解決問題了。
/*
ID: cmykrgb1
PROG: preface
LANG: C++
*/
#include <stdio.h>
#include <string.h>
FILE *fi,*fo;
static char ch[7]={'I','V','X','L','C','D','M'};
long int t[100];
void getrome(int n)
{
    if (n>=1000) //M
    {
        t['M']++;
        getrome(n-1000);
    }else
    if (n>=900) //CM
    {
        t['C']++;
        t['M']++;
        getrome(n-900);
    }
    else
    if (n>=500)
    {
        t['D']++;
        getrome(n-500);
    }
    else
        if (n>=400)
        {
            t['C']++;
            t['D']++;
            getrome(n-400);
        }
        else
        if (n>=100)
        {
            t['C']++;
            getrome(n-100);
        }
        else
        if (n>=90)
        {
            t['X']++;
            t['C']++;
            getrome(n-90);
        }
        else
        if (n>=50)
        {
            t['L']++;
            getrome(n-50);
        }
        else
        if (n>=40)
        {
            t['X']++;
            t['L']++;
            getrome(n-40);
        }
        else
        if (n>=10)
        {
            t['X']++;
            getrome(n-10);
        }
        else
        if (n>=9)
        {
            t['I']++;
            t['X']++;
            getrome(n-9);
        }
        else
        if (n>=5)
        {
            t['V']++;
            getrome(n-5);
        }
        else
        if (n>=4)
        {
            t['I']++;
            t['V']++;
            getrome(n-4);
        }
        else
        if (n>=1)
        {
            t['I']++;
            getrome(n-1);
        }
}
int main(void)
{
    int n,i;char c;
    fi=fopen("preface.in","r");
    fo=fopen("preface.out","w");
    fscanf(fi,"%d",&n);
    fclose(fi);
    for (i=1;i<=n;i++)
        getrome(i);
    for (i=0;i<=6;i++)
        if (t[ch[i]]>0)
            fprintf(fo,"%c %ldn",ch[i],t[ch[i]]);
    fclose(fo);
    return 0;
}