USACO Preface Numbering 构造

一开始看到这道题目的时候,感觉好难

还要算出罗马的规则。

但是仔细一看,数据规模很小, n 只给到3500

看完题目给出了几组样例之后就有感觉了

解题方法就是:

n的每个十进制数 转换成相应的罗马数字,然后统计每个罗马数字出现的次数即可

还是一道简单的构造题。

(以下摘自https://www.byvoid.com/blog/usaco-221preface-numbering/)

转化有以下规则:

1、数较大部分在前,较小部分在后

2、表示10整倍数的字母(I X C M)最多可以累加三次

3、要累加4次的数应该将比该数的字母稍大的表示5整倍数或是10的整倍数的字母在后,累加的字母在前(例如IV XL CD CM)

了解以上规则后发现并不需要实际“转化”出罗马数字,而只用统计每个字母出现的次数。

My Source Code:

/*
ID: wushuai2
PROG: preface
LANG: C++
*/
//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cmath>
#include <stack>
#include <string>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <vector>
#include <algorithm>
#define Max(a,b) (((a) > (b)) ? (a) : (b))
#define Min(a,b) (((a) < (b)) ? (a) : (b))
#define Abs(x) (((x) > 0) ? (x) : (-(x)))
#define MOD 1000000007
#define pi acos(-1.0)

using namespace std;

typedef long long           ll      ;
typedef unsigned long long  ull     ;
typedef unsigned int        uint    ;
typedef unsigned char       uchar   ;

template<class T> inline void checkmin(T &a,T b){if(a>b) a=b;}
template<class T> inline void checkmax(T &a,T b){if(a<b) a=b;}

const double eps = 1e-7      ;
const int M = 660000         ;
const ll P = 10000000097ll   ;
const int INF = 0x3f3f3f3f   ;
const int MAX_N = 20         ;
const int MAXSIZE = 101000000;

int N, ans[10];
string op[5][10] = {
                    {},
                    {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"},
                    {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"},
                    {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"},
                    {"", "M", "MM", "MMM"}
};

void add(string str){
    int i, j;
    for(i = 0; i < str.length(); ++i){
        if(str[i] == ‘I‘)   ++ans[1];
        else if(str[i] == ‘V‘)  ++ans[2];
        else if(str[i] == ‘X‘)  ++ans[3];
        else if(str[i] == ‘L‘)  ++ans[4];
        else if(str[i] == ‘C‘)  ++ans[5];
        else if(str[i] == ‘D‘)  ++ans[6];
        else if(str[i] == ‘M‘)  ++ans[7];
    }
}

int main() {
    ofstream fout ("preface.out");
    ifstream fin ("preface.in");
    int i, j, k, t, n, s, c, w, q;
    fin >> N;
    for(i = 1; i <= N; ++i){
        int temp_g = i % 10;
        string temp = op[1][temp_g];
        add(temp);
        if(i < 10)  continue;
        int temp_s = (i / 10) % 10;
        temp = op[2][temp_s];
        add(temp);

        if(i < 100) continue;
        int temp_b = (i / 100) % 10;
        temp = op[3][temp_b];
        add(temp);

        if(i < 1000) continue;
        int temp_q = i / 1000;
        temp = op[4][temp_q];
        add(temp);
    }
    int flag = -1;
    for(i = 7; i >= 1; --i){
        if(ans[i]){
            flag = i;
            break;
        }
    }
    for(i = 1; i <= flag; ++i){
        if(i == 1){
            fout << "I" << ‘ ‘ << ans[i] << endl;
        } else if(i == 2){
            fout << "V" << ‘ ‘ << ans[i] << endl;
        } else if(i == 3){
            fout << "X" << ‘ ‘ << ans[i] << endl;
        } else if(i == 4){
            fout << "L" << ‘ ‘ << ans[i] << endl;
        } else if(i == 5){
            fout << "C" << ‘ ‘ << ans[i] << endl;
        } else if(i == 6){
            fout << "D" << ‘ ‘ << ans[i] << endl;
        } else if(i == 7){
            fout << "M" << ‘ ‘ << ans[i] << endl;
        }
    }

    fin.close();
    fout.close();
    return 0;
}
时间: 2024-12-14 18:40:46

USACO Preface Numbering 构造的相关文章

usaco Preface Numbering

题目算法不难,难的是读懂题意,意思是从1到N的数字转换成罗马数字,然后统计所有数字中的各种字母出现的次数 对于每个数,用贪心的方法转换为罗马数字,然后统计就好了 /* ID: modengd1 PROG: preface LANG: C++ */ #include <iostream> #include <stdio.h> #include <memory.h> #include <string> #include <cstring> using

USACO:2.2.1 Preface Numbering 序言页码

USACO:2.2.1 Preface Numbering 序言页码 一.题目描述 ★Preface Numbering 序言页码 一类书的序言是以罗马数字标页码的.传统罗马数字用单个字母表示特定的数值,一下是标准数字 表: 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)从不连续出现. 除了下一个规则,一般来说,字符

USACO Section 2.2 Preface Numbering

/* ID: lucien23 PROG: preface LANG: C++ */ #include <iostream> #include <fstream> #include <string> #include <map> using namespace std; int main() { ifstream infile("preface.in"); ofstream outfile("preface.out")

USACO 2.2 Preface Numbering

Preface Numbering A certain book's prefaces are numbered in upper case Roman numerals. Traditional Roman numeral values use a single letter to represent a certain subset of decimal numbers. Here is the standard set: I 1 L 50 M 1000 V 5 C 100 X 10 D 5

【USACO 2.2】Preface Numbering (找规律)

求 1-n 的所有罗马数字表达中,出现过的每个字母的个数. 分别对每个数的罗马表达式计算每个字母个数. 对于十进制的每一位,都是一样的规则,只是代表的字母不同. 于是我们从最后一位往前考虑,当前位由字母 s[i] 代表 1,字母 s[i+1] 代表 5,s[i+2] 代表 10(在下一次代表1). 每一位考虑完 i+=2; num[i] 为当前位为i对应的 s[i] 的个数,当前位为 4~8 时,s[i+1] 出现 1 次,当前位为 9 时,s[i+2] 出现一次. http://train.u

USACO Section 2.1: Preface Numbering

看网上的,太琐碎 1 /* 2 ID: yingzho2 3 PROG: preface 4 LANG: C++ 5 */ 6 #include <iostream> 7 #include <fstream> 8 #include <string> 9 #include <map> 10 #include <vector> 11 #include <set> 12 #include <algorithm> 13 #incl

[USACO][枚举]Preface Numbering

题意: 输入一个数字N,输出[1,N]中数字转化为罗马数字之后每个字母出现的次数. 思路: 暴力过的...写了一个阿拉伯数字转换罗马数字的程序,然后枚举数字string找的字母. 遇到的坑就是罗马数字没有450的简短表示!! leetcode上面有罗马数字和阿拉伯数字互相准换的题目,可能是受这个影响吧...... Analysis的题解里面有这些值得学习的地方:* strcat把两个char[]连接起来 剩下的题解没详细地去看懂>< 1 /* 2 ID :ggy_7781 3 TASK :pr

洛谷 P1465 [USACO2.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 有时,一个可表示为10

2.2.1 Preface Numbering

数字比较小,所以题目的难点就转到了,阿拉伯数字向罗马数字转化的过程了. 转化也不难.我直接手算了,值得注意的是8的写法VIII(不是IIX). 整体来说不难.只要观察出每一位是相互独立的就行. 具体代码如下: /* ID: awsd1231 PROG: preface LANG: C++ */ #include<iostream> #include<cstdio> #include<vector> #include<map> using namespace