1 条题解

  • 0
    @ 2025-5-25 17:26:35

    题目分析

    本题要求将循环小数表示的字符串转换为最简分数,且分母最小。关键在于确定循环节的位置,计算对应的分数,并选择分母最小的解。

    解题思路

    循环节判断: 对于小数点后的数字序列,枚举所有可能的循环节起点i和终点j,判断从i到j是否为循环节(即后续数字是否重复该序列)。 分数计算: 纯循环小数(循环节从第一位开始): 设循环节长度为l,则分数为循环节数值 / (10l1),如0.333...对应3/9=1/3(10^l - 1),如0.333...对应3/9=1/3。 混循环小数(循环节前有非循环部分): 设非循环部分长度为a,循环节长度为b,则分数为(非循环部分数值 *(10b1)+ (10^b - 1) + 循环节数值) / (10a(10b1))(10^a * (10^b - 1)),如$0.12333...对应(12*(10-1)+3)/(10^2*(10-1)) = 111/900 = 37/300$。 最简分数选择: 枚举所有可能的循环节后,计算对应的分数并约分,选择分母最小的分数。若分母相同,选择分子较小的(确保最简)。 #include #include // 添加头文件以声明scanf和printf using namespace std; typedef unsigned long long ll;

    int shuwei[2023]; int len; ll num; ll ansFenzi, ansFenmu; char str[2023]; ll tenPow[2023]; ll fenzi, fenmu, fenziXunhuan, fenmuXunhuan, fenziBuXunhuan, fenmuBuXunhuan;

    void initTenPow() { tenPow[0] = 1; for (int i = 1; i <= 18; i++) { tenPow[i] = tenPow[i - 1] * 10; } }

    bool input() { scanf("%s", str); // 使用scanf读取输入字符串 if (str[1] == '\0') { // 处理输入为"0"的情况 return false; } num = 0, len = 0; int i = 2; // 跳过"0."部分 while (str[i] != '\0' && str[i] != '.') { // 处理可能的"..."或直接数字 num = (str[i] - '0') + num * 10; shuwei[++len] = str[i] - '0'; i++; } return true; }

    bool judgeXunhuanPossible(int i, int j) { int xunhuanLen = j - i + 1; for (; i + xunhuanLen <= len; i++) { if (shuwei[i] != shuwei[i + xunhuanLen]) { return false; } } return true; }

    ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

    ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

    void calcBuxunhuan(int i, int j) { fenziBuXunhuan = 0, fenmuBuXunhuan = 0; if (i == 1) return; for (int k = 1; k < i; k++) { fenziBuXunhuan = fenziBuXunhuan * 10 + shuwei[k]; } fenmuBuXunhuan = tenPow[i - 1]; ll gcdNum = gcd(fenmuBuXunhuan, fenziBuXunhuan); fenziBuXunhuan /= gcdNum; fenmuBuXunhuan /= gcdNum; }

    void calcXunhuan(int i, int j) { fenziXunhuan = 0; for (int k = i; k <= j; k++) { fenziXunhuan = fenziXunhuan * 10 + shuwei[k]; } fenmuXunhuan = tenPow[j - i + 1] - 1; ll gcdNum = gcd(fenmuXunhuan, fenziXunhuan); fenziXunhuan /= gcdNum; fenmuXunhuan /= gcdNum; if (i != 1) { fenmuXunhuan *= tenPow[i - 1]; gcdNum = gcd(fenmuXunhuan, fenziXunhuan); fenziXunhuan /= gcdNum; fenmuXunhuan /= gcdNum; } }

    void calcWholeFenshu() { if (fenziBuXunhuan != 0) { ll lcmNum = lcm(fenmuBuXunhuan, fenmuXunhuan); fenziXunhuan *= lcmNum / fenmuXunhuan; fenziBuXunhuan *= lcmNum / fenmuBuXunhuan; fenzi = fenziXunhuan + fenziBuXunhuan; fenmu = lcmNum; ll gcdNum = gcd(fenmu, fenzi); fenmu /= gcdNum; fenzi /= gcdNum; } else { fenzi = fenziXunhuan; fenmu = fenmuXunhuan; } if (ansFenmu > fenmu || (ansFenmu == fenmu && fenzi < ansFenzi)) { ansFenmu = fenmu; ansFenzi = fenzi; } }

    void initAnsFenziFenmu() { ansFenzi = num; ansFenmu = tenPow[len] - 1; ll gcdNum = gcd(ansFenmu, ansFenzi); ansFenzi /= gcdNum; ansFenmu /= gcdNum; }

    int main() { initTenPow(); while (input()) { initAnsFenziFenmu(); for (int i = 1; i <= len; i++) { for (int j = i; j <= len; j++) { if (judgeXunhuanPossible(i, j)) { calcBuxunhuan(i, j); calcXunhuan(i, j); calcWholeFenshu(); } } } printf("%lld/%lld\n", ansFenzi, ansFenmu); // 使用printf输出结果 } return 0; }

    • 1

    信息

    ID
    931
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者