1 条题解
-
0
题意分析
- 背景:在Divido星球上,由于计算器的普及,学生们不会用纸笔进行长除法运算了。星球政府要对小学生进行数学技能测试,且是选择题形式,学生只需计算两个数相除时循环节的长度。又因为该星球上不同智慧物种手指数量不同,所以数字系统的基数也不同。
- 问题:给定一个基数(b)((2 \leq b \leq 36)),以及基数为(b)的分子(x)和分母(y)((0 < y \leq 100000_{10})),需要计算分数(q = x/y)在基数(b)展开式中的循环节长度。有理数(q)在基数(b)下的展开式中,数位是基数的幂的系数((q = q_nq_{n - 1}\cdots q_0.q_{-1}q_{-2}\cdots=\sum_{-\infty\leq i\leq n}q_ib^i) )。如果分数在基数(b)下有有限展开式(即后面所有数位都是(0)),则循环节长度为(0)。
- 输入:第一行是分数的数量。对于每个分数,先输入基数(b)(十进制数),然后输入分子(x)和分母(y)(基数为(b),不在(0\cdots9)范围内的数字用从“(a)”或“(A)”开始的字母表示,大小写无关),它们之间用单个空格分隔。
- 输出:每个测试用例输出以“Scenario #(i):”开头((i)从(1)开始),然后输出(x/y)在基数(b)展开式中循环节的长度(以十进制数形式),最后用一个空行结束该测试用例的输出。
解题思路
- 转换基数:编写函数
convertToDec
,将基数为(b)的字符串形式的数转换为十进制整数。遍历字符串中的每个字符,如果是数字字符,则将其转换为对应的数字;如果是字母字符,则将其转换为对应的(10)以上的数字,然后根据基数(b)进行计算。 - 计算循环节长度:编写函数
calculatePeriodLength
来计算循环节长度。使用一个无序映射remainderIndex
来记录每次除法运算后的余数及其出现的位置。初始时,计算分子除以分母的余数remainder
。然后进入循环,只要余数不为(0)且该余数尚未在映射中出现过,就将余数及其当前位置记录到映射中,并计算下一次除法运算的余数(通过将当前余数乘以基数(b)再对分母取余得到),同时位置索引index
加(1)。当余数为(0)时,说明分数是有限小数,循环节长度为(0);当余数再次出现时,说明找到了循环节,循环节长度为当前位置索引index
减去该余数首次出现时的位置索引。 - 主函数逻辑:在
main
函数中,首先读取测试用例的数量numCases
。对于每个测试用例,读取基数(b),以及分子和分母的字符串表示xStr
和yStr
。将它们转换为十进制整数x
和y
后,调用calculatePeriodLength
函数计算循环节长度periodLength
,并按照输出格式要求进行输出。
标程(C++)
#include <iostream> #include <string> #include <unordered_map> #include <cmath> using namespace std; // 将b进制字符串转换为十进制整数 int convertToDec(const string& num, int b) { int res = 0; for (char c : num) { int digit; if (isdigit(c)) { digit = c - '0'; if (digit >= b) return -1; // 非法数字 } else { digit = tolower(c) - 'a' + 10; if (digit >= b) return -1; // 非法数字 } res = res * b + digit; } return res; } int calculatePeriodLength(int b, int x, int y) { if (y == 0) return 0; // 避免除以零 unordered_map<int, int> remainderIndex; int remainder = x % y; int index = 0; while (remainder != 0 && remainderIndex.find(remainder) == remainderIndex.end()) { remainderIndex[remainder] = index; remainder = (remainder * b) % y; index++; } if (remainder == 0) { return 0; } else { return index - remainderIndex[remainder]; } } int main() { int numCases; cin >> numCases; for (int i = 1; i <= numCases; ++i) { int b; string xStr, yStr; cin >> b >> xStr >> yStr; int x = convertToDec(xStr, b); int y = convertToDec(yStr, b); if (x == -1 || y == -1) { cout << "Scenario #" << i << ":\nInvalid number!\n\n"; continue; } int periodLength = calculatePeriodLength(b, x, y); cout << "Scenario #" << i << ":\n"; cout << periodLength << "\n\n"; } return 0; }
- 1
信息
- ID
- 797
- 时间
- 1000ms
- 内存
- 30MiB
- 难度
- 10
- 标签
- 递交数
- 7
- 已通过
- 0
- 上传者