P1015 [NOIP 1999 普及组] 回文数

【题解-洛谷】P1015 [NOIP 1999 普及组] 回文数 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。位之内),求最少经过几步可以得到回文数。步以内得到回文数,输出格式形如。步)不可能得到回文数,则输出。在这里的一步是指进行了一次。进制的加法,上例最少用了。为最少得到回文数的步数。例如:给定一个十进制数。写一个程序,给定一个。 阅读详情

记录141

#include<bits/stdc++.h> 
using namespace std; 
int n; // 进制数 N
int a[200],len; // a数组用来倒序存储大数,len记录当前大数的长度

// 判断当前数组 a 是否是回文数
bool f(){
    for(int i=0;i<len/2;i++){
        if(a[i]!=a[len-1-i]) return false;
    }
    return true;
}

// 高精度 N 进制加法:将数组 a 与它的倒序相加
void add(){
    int b[200]; // 用来存 a 的倒序
    // 1. 先把 a 倒序存入 b
    for(int i=0;i<len;i++) b[i]=a[len-1-i];
    
    // 2. 模拟竖式加法
    for(int i=0;i<len;i++){
        a[i]+=b[i]; // 对应位相加
        a[i+1]+=a[i]/n; // 处理进位
        a[i]%=n; // 保留当前位的余数
    }
    
    // 3. 如果最高位产生了进位,长度要加1
    if(a[len]>0) len++;
}

int main(){ // 主函数入口
    ios::sync_with_stdio(false); // 关闭同步,加速IO
    cin.tie(0);
    
    string s; // 用来读入初始的 N 进制数 M
    cin>>n>>s;
    
    // 将字符串倒序转换成数字存入数组 a(方便从个位开始加)
    len=s.size();
    for(int i=0;i<len;i++){
        char c=s[len-1-i]; // 倒着取字符
        if(c>='0'&&c<='9') a[i]=c-'0'; // 数字字符转数字
        else a[i]=c-'A'+10; // 字母 A-F 转 10-15
    }
    
    int step=0; // 记录步数
    while(step<=30){
        if(f()){ // 如果已经是回文数
            cout<<"STEP="<<step<<"\n";
            return 0; // 直接结束程序
        }
        add(); // 执行一次高精度加法
        step++; // 步数加1
    }
    
    // 如果循环跑完30步还没找到
    cout<<"Impossible!\n";
    return 0;
}

题目传送门https://www.luogu.com.cn/problem/P1015


前言

我是一名专注信奥赛(CSP-J/S、NOIP)的教练。

  • 如果你觉得这篇题解对你有帮助,欢迎点击关注我的优快云账号,我会持续更新高质量算法解析。
  • 我深知算法思维的构建远比单纯通过题目更重要,本系列题解不局限于AC代码的堆砌,而是致力于拆解题目背后的逻辑链条与核心知识点
  • 备赛路上若遇瓶颈,欢迎随时评论或私信,我将甄选典型疑难问题,通过视频讲解或撰写专项文章的形式,为你提供深度答疑。

核心解题思路

这道题是一道非常经典的高精度运算与字符串处理结合的问题。

  1. 数据规模分析:
    题目中给出的 N 进制数 M 长度不超过 100 位。在 C++ 等语言中,普通的整数类型(如 long long)最多只能存储 19 位左右的十进制数。因此,我们必须使用高精度算法,即用数组来模拟大数的每一位进行运算。

  2. 算法设计(高精度加法 + 模拟):
    题目要求我们不断执行“将当前数与其倒序数相加”的操作,直到结果变为回文数。我们可以按照以下步骤模拟:

    • 数据存储:将输入的字符串倒序存入一个整型数组中(数组下标 0 对应个位,方便处理进位)。
    • 回文判定:每次加法前,检查当前数组表示的数是否是回文数。
    • 高精度 N 进制加法:模拟竖式加法,将数组与它的倒序对应位相加,并处理 N 进制的进位。
    • 步数限制:题目限制最多 30 步,如果超过 30 步仍未得到回文数,则输出 Impossible!。

代码分块详细解释

1. 头文件、全局变量与回文判定函数

#include<bits/stdc++.h> 
using namespace std; 
int n; // 进制数 N
int a[200], len; // a数组用来倒序存储大数,len记录当前大数的长度

// 判断当前数组 a 是否是回文数
bool f(){
    for(int i=0; i<len/2; i++){
        if(a[i] != a[len-1-i]) return false;
    }
    return true;
}
  • 详细分析:a[200] 是高精度运算的核心容器,因为初始长度最多 100 位,经过最多 30 次加法后,长度翻倍也远小于 200,所以数组大小足够。f() 函数通过双指针思想,从数组的两端向中间遍历,只要有一对对应位置的数字不相等,就说明不是回文数。

2. 核心逻辑:高精度 N 进制加法

// 高精度 N 进制加法:将数组 a 与它的倒序相加
void add(){
    int b[200]; // 用来存 a 的倒序
    // 1. 先把 a 倒序存入 b
    for(int i=0; i<len; i++) b[i] = a[len-1-i];
    
    // 2. 模拟竖式加法
    for(int i=0; i<len; i++){
        a[i] += b[i];      // 对应位相加
        a[i+1] += a[i] / n; // 处理进位(除以进制数 n)
        a[i] %= n;         // 保留当前位的余数(对进制数 n 取模)
    }
    
    // 3. 如果最高位产生了进位,长度要加1
    if(a[len] > 0) len++;
}
  • 详细分析:这是本题最核心的部分。
    • 倒序备份:由于我们要将 a 和它的倒序相加,而 a 本身在加法过程中会被修改,所以必须先用一个临时数组 b 把 a 的倒序存起来。
    • 竖式加法与进位:从个位(下标 0)开始,将 a[i] 和 b[i] 相加。因为是 N 进制,所以满 N 就要进 1。a[i] / n 得到进位的值,加到下一位 a[i+1] 上;a[i] % n 得到当前位保留的数字。
    • 长度更新:如果最高位(a[len-1])相加后产生了进位,这个进位会落在 a[len] 上,此时大数的实际长度就需要增加 1。

3. 主函数:输入处理与倒序转换

int main(){ 
    ios::sync_with_stdio(false); 
    cin.tie(0);
    
    string s; // 用来读入初始的 N 进制数 M
    cin >> n >> s;
    
    // 将字符串倒序转换成数字存入数组 a(方便从个位开始加)
    len = s.size();
    for(int i=0; i<len; i++){
        char c = s[len-1-i]; // 倒着取字符
        if(c >= '0' && c <= '9') a[i] = c - '0';      // 数字字符转数字
        else a[i] = c - 'A' + 10; // 字母 A-F 转 10-15
    }
  • 详细分析:由于输入的数可能包含字母(如 16 进制中的 A-F),且长度很长,必须用 string 读入。为了符合人类做竖式加法的习惯(从个位开始算),我们将字符串倒序存入数组 a。例如输入 "87",a[0] 存 7,a[1] 存 8。同时,通过 ASCII 码的运算,将字符完美转换为对应的十进制数值。

4. 主循环:模拟步进与结果输出

    int step = 0; // 记录步数
    while(step <= 30){
        if(f()){ // 如果已经是回文数
            cout << "STEP=" << step << "\n";
            return 0; // 直接结束程序
        }
        add(); // 执行一次高精度加法
        step++; // 步数加1
    }
    
    // 如果循环跑完30步还没找到
    cout << "Impossible!\n";
    return 0;
}
  • 详细分析:这里采用了 while 循环来模拟题目要求的操作步骤。每次循环开始时,先判断当前数是否已经是回文数(注意:初始输入的数本身可能就是回文数,此时步数为 0)。如果不是,就调用 add() 执行一次加法,并将步数加 1。如果循环正常结束(即 step 超过了 30),说明在限制步数内无法得到回文数,输出 Impossible!。

 核心逻辑总结表

代码模块核心变量/操作精炼作用解决的痛点
高精度存储int a[200]用整型数组倒序存储大数突破了普通整数类型的位数限制,能够处理 100 位以上的超大数
字符转换c-'0' 与 c-'A'+10将 N 进制字符转换为对应数值完美兼容了 2-10 进制以及 16 进制(包含字母)的输入
回文判定f() 函数双指针比对数组两端快速判断当前高精度数是否满足题目要求的终止条件
竖式加法a[i+1] += a[i]/n模拟 N 进制的进位操作实现了任意进制下的大数加法,是本题的核心算法
动态长度if(a[len]>0) len++处理最高位进位导致的长度增加保证了在多次加法后,数组的有效长度始终是正确的
步数模拟while(step<=30)限制最大操作次数并模拟过程严格按照题目要求,在 30 步内寻找答案或判定无解
P1015 [NOIP1999 普及组] 回文数/1309:【例1.6】回文数(Noip1999) 没想到我也有求助的亿天 P1015 [NOIP1999 普及组] 回文数 提交76.36k 通过24.62k 时间限制1.00s 内存限制125.00MB 提交答案加入题单复制题目 做题计划(首页) 个人题单 团队题单 保存 选择团队 保存 题目提供者CCF_NOI 难度普及- 历史分数100 提交记录查看题解 标签 NOIp 普及组1999 查看算法标签 进入讨论版 相关讨论 查看讨论 推荐题目 查看推荐 洛谷推荐关闭 复制Markd... 阅读详情

相关推荐

P1015 [NOIP1999 普及组] 回文数

若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。例如:给定一个十进制数56,将56加65(即把56从右向左读),得到121是一个回文数。又如:对于十进制数8787781651655617267266271353135335314884在这里的一步是指进行了一次N进制的加法,上例最少用了4步得到回文数4884。写一个程序,给定一个N2≤N≤10或N16)进制数M100位之内),求最少经过几步可以得到回文数。

小天狼星_布莱克 的博客 1426

【洛谷 P1015 NOIP 1999 普及组】 回文数

若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。例如:给定一个十进制数56,将56加65(即把56从右向左读),得到121是一个回文数。又如:对于十进制数8787781651655617267266271353135335314884在这里的一步是指进行了一次N进制的加法,上例最少用了4步得到回文数4884。写一个程序,给定一个N2≤N≤10或N16)进制数M100位之内),求最少经过几步可以得到回文数。

Chow_Ssehc的博客 1146

题解:洛谷 P1015 [NOIP 1999 普及组] 回文数

等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。位之内),求最少经过几步可以得到回文数。步以内得到回文数,输出格式形如。步)不可能得到回文数,则输出。在这里的一步是指进行了一次。进制的加法,上例最少用了。为最少得到回文数的步数。例如:给定一个十进制数。写一个程序,给定一个。#普及-# #高精度#

团爸讲算法 712

P1015 [NOIP1999 普及组] 回文数 题解

P1015 [NOIP1999 普及组] 回文数 题解

yaosichengalpha的博客 1154

RocketMQ 为什么要自己做一个 NameServer ?RocketMQ 5.x 版本中的 proxy、controller 和 container 分别有什么用 ?

1.独立运行的分散结构 2.简化实现,容忍部分数据不一致 Proxy:多语言支持、简化开发 Controller: 提高 Broker 的性能 Container:提高资源利用率,平衡负载

xaiobit_hl的博客 1490

硬件基础(4):(6)高精度ADC设计中模拟地与数字地的划分与连接

在实际 PCB 设计中,**接地与布线**对于获得干净的参考电压和高精度 ADC 测量至关重要。下面详细阐述**如何在硬件层面减少数字噪声耦合到模拟电路、保障参考电压的稳定性**。

FCZlll的博客 2648

【题解】【洛谷P1015】【高精度】—— [NOIP1999 普及组] 回文数

蓝胖子编程教育,是一家面向青少年的编程教育平台。平台为全国青少年提供最专业的编程教育服务,包括提供最新最详细的编程相关资讯、最专业的竞赛指导、最合理的课程规划等。本平台利用趣味性和互动性强的教学方式,旨在激发孩子们对编程的兴趣,培养他们的逻辑思维能力和创造力,让孩子们在轻松愉快的氛围中掌握编程知识,为未来科技人才的培养奠定坚实基础。这里有个小技巧:我们不需要将字符存储起来,而是将其对应的数字存储起来,这样方便编写代码。若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。

Pantheraonca的博客 997

告别SquareLine!用免费的NXP GUI-Guider为海思3516AV300开发LVGL界面(附完整移植流程)

本文详细介绍了如何利用免费的NXP GUI-Guider工具为海思Hi3516AV300开发LVGL界面,包括环境配置、代码移植和性能优化等全流程实战指南。特别针对二维码组件缺失等常见问题提供解决方案,帮助开发者零成本构建高效嵌入式GUI系统。

weixin_28292761的博客 417

每日c/c++题 备战蓝桥杯(洛谷P1015 [NOIP 1999 普及组] 回文数)

本题核心是掌握大数运算在模拟题中的应用关键点在于:正确实现进制转换高效处理大数加法与进位准确判断回文结构实际编程时需特别注意:数组越界问题(动态维护len变量)不同进制的字符处理(0-9和A-F)步骤计数器的初始值与终止条件进制转换的双向实现大数运算的基本技巧模拟算法的优化策略。

m0_74096349的博客 1189

iSLIP算法实战:如何用Python模拟交换机优先级匹配(附完整代码)

本文详细介绍了如何使用Python实现iSLIP算法,模拟交换机优先级匹配过程。通过核心的指针滑动逻辑和迭代循环策略,构建了一个完整的iSLIP算法模拟器,并加入可视化模块以直观展示匹配过程。文章还提供了完整的代码框架和性能优化建议,适合网络工程师和Python开发者直接集成到测试环境中。

weixin_29313239的博客 251

dify进阶:使用 FastAPI 的 StreamingResponse 实现高效的数据流传输

在 FastAPI 框架中,是一个非常有用的工具,它允许你以流的方式发送数据给客户端,而不是一次性加载所有内容到内存中再发送。这对于处理大型文件下载、视频流或者任何需要长时间处理的任务特别有用。

xiezhipu的博客 1434

【题解·洛谷】P1015 [NOIP1999 普及组] 回文数

洛谷P1015 题解

qq_56897740的博客 1453

气象大模型光伏功率预测中的应用:从短期,超短期,中长期的实现与开源代码详解

本文详细介绍了基于大模型的光伏功率预测方法,涵盖超短期(15分钟-1小时)、短期(1-6小时)和中长期(1天-1周)预测。文章首先讨论了数据准备与预处理,包括历史功率、气象、天文和电站特性数据的收集与特征工程。随后,针对不同预测需求,提出了多种深度学习模型:超短期预测采用1DCNN-LSTM混合模型,短期预测使用Transformer模型,中长期预测则通过多尺度特征提取模型和概率预测方法处理不确定性。文章还提供了模型训练、评估、部署和优化的完整流程,并开源了代码实现。未来研究方向包括结合数值天气预报、开发时

专注AI大模型,软件混淆,授权 1583

洛谷 P1015 [NOIP1999 普及组] 回文数

菜鸟生成记(31) P1015 NOIP1999 普及组 回文数 这一题和C语言网上的一模一样(这一题的数据更强一些) #include<bits/stdc++.h> using namespace std; const int N=1e3; char m[N]={0}; int a[N],b[N],sum[N],flag=0,n=0,l=0; int fun(int s[],int len)//判断数组是否为回文串 { for(int i=0;i<len/2;i++)

Thy__father的博客 781

NVIDIA - 人形机器人扼要

人形机器人是仿照人类外形设计的通用双足机器人,旨在与人类并肩工作,提高生产效率。它们能够学习和执行各种任务,如抓取物体、移动集装箱、装卸箱子等。

机器人控制与仿真应用 1291

从零开始用 C# 打造工业级上位机系统:完整项目实战

本文介绍了一个基于C#开发的工业级上位机系统项目。该系统采用分层架构设计,包含通信、数据采集、UI展示、告警日志等模块,支持Modbus协议和串口通信。文章详细阐述了系统架构设计、关键模块实现(如Modbus通信封装、实时数据采集、告警系统等)以及性能优化策略。该项目已在实际工控场景中稳定运行超过1年,具备良好的可扩展性和稳定性,适合有一定C#基础的开发者参考学习工业软件开发实践。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1368
上一篇: P1036 [NOIP 2002 普及组] 选数
下一篇: P1827 [USACO3.4] 美国血统 American Heritage
谢天谢地AC了 | 信奥教练
博客等级 码龄1年 53粉丝 177原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值