USACO 2.2 Preface Numbering
2015-03-17 14:49
417 查看
这道题让我想到了之前Chapter 1的计算星期五的那道题。
罗马数字的书写规律见罗马数字。在我的理解中,罗马数字就是十进制的复杂版,每一个位数上的数字单独转化成一组字母,这样罗马数字的书写就完成了。也就是说,只要计算出每个位数的数字会对应哪几个字母,就可以方便地计算了。比如说,在十位数上的9,其书写一定是XC。
由此,我做了两件事情:
(1) 记录每个位数上1-9的字母组合
(2) 遍历范围内的数字,分离它的每一位,并依次加入总数的计算
附上代码:
#include <iostream>
#include <fstream>
using namespace std;
int nums[7];
int dict[4][10][9];
int N;
void initData()
{
ifstream fin ("preface.in");
int i;
fin >> N;
for (i = 0; i < 4; i ++) {
dict[i][1][i*2] = 1;
dict[i][2][i*2] = 2;
dict[i][3][i*2] = 3;
dict[i][4][i*2] = 1;
dict[i][4][i*2+1] = 1;
dict[i][5][i*2+1] = 1;
dict[i][6][i*2] = 1;
dict[i][6][i*2+1] = 1;
dict[i][7][i*2] = 2;
dict[i][7][i*2+1] = 1;
dict[i][8][i*2] = 3;
dict[i][8][i*2+1] = 1;
dict[i][9][i*2] = 1;
dict[i][9][i*2+2] = 1;
}
}
int main()
{
initData();
ofstream fout ("preface.out");
int i, j;
int m, n;
for (i = 1; i <= N; i ++) {
for (n = 0, m = i; m / 10 != 0; n ++, m /= 10)
for (j = 0; j < 8; j ++)
nums[j] += dict
[m%10][j];
for (j = 0; j < 8; j ++)
nums[j] += dict
[m][j];
}
if (nums[0] != 0)
fout << "I " << nums[0] << endl;
if (nums[1] != 0)
fout << "V " << nums[1] << endl;
if (nums[2] != 0)
fout << "X " << nums[2] << endl;
if (nums[3] != 0)
fout << "L " << nums[3] << endl;
if (nums[4] != 0)
fout << "C " << nums[4] << endl;
if (nums[5] != 0)
fout << "D " << nums[5] << endl;
if (nums[6] != 0)
fout << "M " << nums[6] << endl;
}
其中的dict数组的维数含义是这样的:第一个代表的是位数,第二个是数字本身,第三个代表IV...M的全组。
举个例子来说,比如我遍历到了572这个数字,那么对于其中的5,我应当查看dict[2][5][0...7]这一排;对于其中的7,我应当查看dict[1][7][0...7]这一排;对于其中的2,我应当查看dict[0][2][0...7]这一排。
闲话时间。这道题的用时基本都花在理解题意上了,一旦明白了它的运作方式,逻辑上是没有坑的。我不太喜欢做这种可以hardcode的题目……
罗马数字的书写规律见罗马数字。在我的理解中,罗马数字就是十进制的复杂版,每一个位数上的数字单独转化成一组字母,这样罗马数字的书写就完成了。也就是说,只要计算出每个位数的数字会对应哪几个字母,就可以方便地计算了。比如说,在十位数上的9,其书写一定是XC。
由此,我做了两件事情:
(1) 记录每个位数上1-9的字母组合
(2) 遍历范围内的数字,分离它的每一位,并依次加入总数的计算
附上代码:
#include <iostream>
#include <fstream>
using namespace std;
int nums[7];
int dict[4][10][9];
int N;
void initData()
{
ifstream fin ("preface.in");
int i;
fin >> N;
for (i = 0; i < 4; i ++) {
dict[i][1][i*2] = 1;
dict[i][2][i*2] = 2;
dict[i][3][i*2] = 3;
dict[i][4][i*2] = 1;
dict[i][4][i*2+1] = 1;
dict[i][5][i*2+1] = 1;
dict[i][6][i*2] = 1;
dict[i][6][i*2+1] = 1;
dict[i][7][i*2] = 2;
dict[i][7][i*2+1] = 1;
dict[i][8][i*2] = 3;
dict[i][8][i*2+1] = 1;
dict[i][9][i*2] = 1;
dict[i][9][i*2+2] = 1;
}
}
int main()
{
initData();
ofstream fout ("preface.out");
int i, j;
int m, n;
for (i = 1; i <= N; i ++) {
for (n = 0, m = i; m / 10 != 0; n ++, m /= 10)
for (j = 0; j < 8; j ++)
nums[j] += dict
[m%10][j];
for (j = 0; j < 8; j ++)
nums[j] += dict
[m][j];
}
if (nums[0] != 0)
fout << "I " << nums[0] << endl;
if (nums[1] != 0)
fout << "V " << nums[1] << endl;
if (nums[2] != 0)
fout << "X " << nums[2] << endl;
if (nums[3] != 0)
fout << "L " << nums[3] << endl;
if (nums[4] != 0)
fout << "C " << nums[4] << endl;
if (nums[5] != 0)
fout << "D " << nums[5] << endl;
if (nums[6] != 0)
fout << "M " << nums[6] << endl;
}
其中的dict数组的维数含义是这样的:第一个代表的是位数,第二个是数字本身,第三个代表IV...M的全组。
举个例子来说,比如我遍历到了572这个数字,那么对于其中的5,我应当查看dict[2][5][0...7]这一排;对于其中的7,我应当查看dict[1][7][0...7]这一排;对于其中的2,我应当查看dict[0][2][0...7]这一排。
闲话时间。这道题的用时基本都花在理解题意上了,一旦明白了它的运作方式,逻辑上是没有坑的。我不太喜欢做这种可以hardcode的题目……
相关文章推荐
- USACO 2.2Runaround Numbers
- USACO-Section 2.2 Preface Numbering (数学)
- USACO 2.2 Runaround Numbers
- USACO Section 2.2 Preface Numbering
- USACO - Chapter2 Section 2.2 - Hamming Codes
- USACO-Section2.2 Party Lamps [枚举]
- usaco-2.2-subset-pass
- [2016/7/26][usaco 2.2]Party Lamps
- [usaco]2.2 Subset Sums
- USACO 2.2 序言页码 (MATH)
- USACO 2.2 Party Lamps(乱搞)
- USACO Section 2.2 Subset Sums
- USACO 2.2 分析
- USACO 之 Section 2.2 (已解决)
- USACO-Section2.2 subset[DP]
- USACO-Section2.2 Preface Numbering
- USACO 2.2
- USACO 2.2 集合(DP)
- usaco 2.2 subset...
- USACO 2.2 Subset Sums