1 条题解

  • 0
    @ 2025-4-8 20:47:38

    题意分析

    1. 背景:在Divido星球上,由于计算器的普及,学生们不会用纸笔进行长除法运算了。星球政府要对小学生进行数学技能测试,且是选择题形式,学生只需计算两个数相除时循环节的长度。又因为该星球上不同智慧物种手指数量不同,所以数字系统的基数也不同。
    2. 问题:给定一个基数(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)。
    3. 输入:第一行是分数的数量。对于每个分数,先输入基数(b)(十进制数),然后输入分子(x)和分母(y)(基数为(b),不在(0\cdots9)范围内的数字用从“(a)”或“(A)”开始的字母表示,大小写无关),它们之间用单个空格分隔。
    4. 输出:每个测试用例输出以“Scenario #(i):”开头((i)从(1)开始),然后输出(x/y)在基数(b)展开式中循环节的长度(以十进制数形式),最后用一个空行结束该测试用例的输出。

    解题思路

    1. 转换基数:编写函数 convertToDec,将基数为(b)的字符串形式的数转换为十进制整数。遍历字符串中的每个字符,如果是数字字符,则将其转换为对应的数字;如果是字母字符,则将其转换为对应的(10)以上的数字,然后根据基数(b)进行计算。
    2. 计算循环节长度:编写函数 calculatePeriodLength 来计算循环节长度。使用一个无序映射 remainderIndex 来记录每次除法运算后的余数及其出现的位置。初始时,计算分子除以分母的余数 remainder。然后进入循环,只要余数不为(0)且该余数尚未在映射中出现过,就将余数及其当前位置记录到映射中,并计算下一次除法运算的余数(通过将当前余数乘以基数(b)再对分母取余得到),同时位置索引 index 加(1)。当余数为(0)时,说明分数是有限小数,循环节长度为(0);当余数再次出现时,说明找到了循环节,循环节长度为当前位置索引 index 减去该余数首次出现时的位置索引。
    3. 主函数逻辑:在 main 函数中,首先读取测试用例的数量 numCases。对于每个测试用例,读取基数(b),以及分子和分母的字符串表示 xStryStr。将它们转换为十进制整数 xy 后,调用 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
    上传者