题解:学而思编程 回文质数(一)

【题目来源】

学而思编程:回文质数(一)

【题目描述】

小猴最近在编程课上学习了回文数,并且在数学课上学习质数。

小猴想要知道在 \(L\sim R\) 之间(包含 \(L\)\(R\)),其中有多少个数既是回文数又是质数。请你帮助小猴解答他疑惑。

【输入】

一行两个整数 \(L\)\(R\)

【输出】

一行一个整数,表示在 \(L\sim R\) 之间(包含 \(L\)\(R\)),其中有多少个数既是回文数又是质数。

【输入样例】

7 11

【输出样例】

2

【核心思想】

  1. 问题分析:给定区间 \([L, R]\),统计其中既是回文数又是质数的数的个数。这是一个回文数构造 + 质数判定问题,关键在于高效生成回文数而非遍历整个区间,再对每个回文数判断是否为质数。

  2. 算法选择

    • 回文数构造:通过"前半部分 + 镜像"的方式生成回文数,避免遍历全部数字
    • 质数判定:对每个生成的回文数,用试除法到 \(\sqrt{x}\) 判断是否为质数
    • 奇偶长度分类:分别构造奇数长度和偶数长度的回文数
  3. 关键步骤

    • 初始化:读取 \(L\)\(R\)
    • 回文数构造(遍历 \(i\)\(0\)\(999\)):
      • 奇数长度回文work(i, i),将 \(i\) 作为前半部分,镜像拼接。例如 \(i = 123\),生成 \(12321\)
      • 偶数长度回文work(10 * i + j, i),在 \(i\) 和镜像之间插入中间数字 \(j\)\(0 \leq j \leq 9\))。例如 \(i = 12, j = 3\),生成 \(12321\)
    • work 函数
      • 将后半部分 \(b\) 的数字反向添加到 \(a\) 后面,构造完整回文数
      • 若回文数在 \([L, R]\) 内且是质数:ans++
    • 质数判定 isprime(x)
      • \(x \leq 1\):返回 false
      • 遍历 \(i\)\(2\)\(\sqrt{x}\):若 \(x \bmod i = 0\) 则返回 false
      • 否则返回 true
    • 输出 ans
  4. 时间/空间复杂度

    • 时间复杂度:\(O(1000 \times 10 \times \sqrt{R})\),生成约 \(10000\) 个回文数,每个质数判定 \(O(\sqrt{R})\)
    • 空间复杂度:\(O(1)\),仅需常数变量
  5. 回文数构造的核心思想

    • 生成优于枚举:直接构造回文数的数量远小于区间内的数字总数(尤其大区间时),大幅降低搜索空间
    • 镜像拼接:回文数的前半部分唯一确定整个数,通过数字反转和拼接实现构造
    • 奇偶分类:奇数长度回文有中心数字,偶数长度无中心数字,分别用 work(i, i)work(10*i+j, i) 覆盖
    • 范围过滤:构造后立即检查是否在 \([L, R]\) 内,避免无效质数判定
    • 适用于"回文数 + 其他约束"的计数问题,构造法将线性枚举优化为对数级生成

【算法标签】

质数

【代码详解】

#include <bits/stdc++.h>
using namespace std;
#define int long long
int l, r, ans;  // 查询区间[l,r],答案ans

// 判断素数
bool isprime(int x)
{
    if (x <= 1) return false;  // 小于等于1不是素数
    for (int i = 2; i * i <= x; i++)  // 检查到√x
    {
        if (x % i == 0) return false;  // 有因数,不是素数
    }
    return true;  // 是素数
}

// 构造回文数并判断
int work(int a, int b)
{
    while (b > 0)  // 将b的数字反向添加到a后面
    {
        a = a * 10 + b % 10;  // 将b的最后一位加到a
        b /= 10;  // 去掉b的最后一位
    }
    // 检查a是否在区间内且是素数
    if (l <= a && a <= r && isprime(a) == true)
    {
        return 1;  // 满足条件
    }
    else
    {
        return 0;  // 不满足条件
    }
}

signed main()
{
    cin >> l >> r;  // 输入查询区间

    // 生成所有可能的回文数
    for (int i = 0; i < 1000; i++)  // 生成3位数以内的回文基础
    {
        // 奇数长度回文:work(i, i) 如12321
        ans += work(i, i);

        // 偶数长度回文:work(10*i+j, i) 如123321
        for (int j = 0; j <= 9; j++)  // 中间插入数字j
        {
            ans += work(10 * i + j, i);
        }
    }
    cout << ans << endl;  // 输出结果
    return 0;
}

【运行结果】

7 11
2
posted @ 2026-07-05 14:40  团爸讲算法  阅读(5)  评论(0)    收藏  举报