P1643 完美数 题解

完美数

首先,介绍一下这篇题解的特邀嘉宾:ChatGPT4.0

传送门

题目描述

考古队员小星在一次考察中意外跌入深渊,穿越到了一个神秘的荒漠。这里有许多超越他认识的事物存在,例如许多漂浮在空中的建筑,例如各种奇怪的动物。

在这片荒漠的中央,小星发现了一个巨大的类似神庙的建筑,为了脱离这片空间,小星决定前去探索。

在临近神庙大门时,突然跳出了一个人面狮(不是斯芬达克斯)!它咆哮着:

“我是这里的守卫,要想通过这里,必须回答出我的一系列问题,否则,我就吃了你。”

人面狮告诉小星,问题总是这样的模式:比 X X X 大的第 N N N 小的回文数是多少。

小星想,这个问题看来不难,于是问答开始了。

“比 1 1 1 大的第 1 1 1 小回文数数是多少?”

2 2 2

“比 17 17 17 大的第 2 2 2 小的回文数是多少?”

33 33 33

“比 98 98 98 大的第 2 2 2 小的回文数是多少?”

101 101 101

“那比 948237 大的第 2339587 小的回文数是多少?”

“*(•%(*•—#•#¥*—%(*—%”

为了避免被守卫吃掉,小星只好打开笔记本想借助电脑,却意外地发现可以通过网络(网通?电信?宇宙通?)找到你,于是这个问题就拜托给你了!

输入格式

本题每一个数据包含有多组数据。

对于每一个数据包,第一行一个数 T T T,表示总共有 T T T 组数据。

对于每一组数据,包括两行,第一行为 X X X,第二行为 N N N,表示当前询问是比 X 大的第 N 小的回文数是多少。

输出格式

对于每一组数据输出一行,表示询问的结果。

样例 #1

样例输入 #1

3
1
1
17
2
98
2

样例输出 #1

2
33
101

提示

【数据规模】

20 % 20 \% 20% 的数据满足 X ≤ 200000 X \le 200000 X200000 N ≤ 1000 N \le 1000 N1000

30 % 30 \% 30% 的数据满足 X , N X, N X,Nlongint 范围之内,且答案也在 longint 范围之内。

100 % 100 \% 100% 的数据满足 X , N ≤ 10 10000 X, N \le {10}^{10000} X,N1010000,答案 ≤ 10 20001 \le {10}^{20001} 1020001 T ≤ 10 T \le 10 T10

以上来自洛谷 以上来自洛谷 以上来自洛谷

解题思路(所有思路与代码都由ChatGPT特供,本人只加以润色)

暴力思路(ChatGPT友情赞助)

  1. 首先需要找到比X大的第N小的回文数,可以从X+1开始逐个判断是否是回文数,直到找到第N个回文数为止。
  2. 判断一个数是否是回文数可以将其转化为字符串,然后判断字符串是否是回文字符串。
  3. 找到第N个回文数后输出即可。
伪代码:
  1. 读入T
  2. 循环T次:
    1. 读入X和N
    2. 初始化count为0,ans为0
    3. 从X+1开始逐个判断是否是回文数,直到count等于N为止:
      1. 将当前数转化为字符串
      2. 判断该字符串是否是回文字符串:
        1. 初始化i为0,j为字符串长度-1
        2. 循环i小于j:
          1. 如果字符串第i个字符不等于第j个字符,则不是回文字符串跳出循环
          2. 否则,i加1,j减1
        3. 如果i大于等于j,表示是回文字符串,将count加1
      3. 如果count等于N,表示找到了第N个回文数,将ans赋值为当前数
    4. 输出ans
Code1
#include <iostream>
#include <string>
using namespace std;bool isPalindrome(string num) {int i = 0, j = num.length() - 1;while (i < j) {if (num[i] != num[j]) {return false;}i++;j--;}return true;
}int main() {int T;cin >> T;for (int t = 0; t < T; t++) {int X, N;cin >> X >> N;int count = 0;int ans = 0;for (int num = X + 1; count < N; num++) {string numStr = to_string(num);if (isPalindrome(numStr)) {count++;ans = num;}}cout << ans << endl;}return 0;
}

暴力优化(依旧是ChatGPT大佬提供)

要降低时间复杂度,可以采用以下方法:

  • 判断一个数是否是回文数,可以不用将其转化为字符串,而是直接在数字上进行操作。
  • 可以利用回文数的对称性质来判断是否是回文数,即从两端往中间进行比较。
  • 找到第N个回文数后,不需要继续判断后面的数,可以直接跳出循环。
Code2
#include <iostream>
using namespace std;bool isPalindrome(int num) {int reversedNum = 0;int temp = num;while (temp > 0) {int digit = temp % 10;reversedNum = reversedNum * 10 + digit;temp /= 10;}return num == reversedNum;
}int main() {int T;cin >> T;for (int t = 0; t < T; t++) {int X, N;cin >> X >> N;int count = 0;int ans = 0;for (int num = X + 1; count < N; num++) {if (isPalindrome(num)) {count++;ans = num;}}cout << ans << endl;}return 0;
}

继续优化(依然是它)

要进一步降低时间复杂度,可以采用以下方法:

  • 判断一个数是否是回文数的操作可以进一步优化。可以只判断一半的数字,而不需要全部反转,然后与另一半进行比较。
  • 可以通过找到下一个回文数的规律来快速找到第N个回文数。

优化后的代码如下:

Code3
#include <iostream>
using namespace std;bool isPalindrome(int num) {if (num < 0 || (num % 10 == 0 && num != 0)) {return false;}int reversedNum = 0;while (num > reversedNum) {reversedNum = reversedNum * 10 + num % 10;num /= 10;}return num == reversedNum || num == reversedNum / 10;
}int getNextPalindrome(int num) {num++;while (!isPalindrome(num)) {num++;}return num;
}int main() {int T;cin >> T;for (int t = 0; t < T; t++) {int X, N;cin >> X >> N;int ans = getNextPalindrome(X);for (int i = 1; i < N; i++) {ans = getNextPalindrome(ans);}cout << ans << endl;}return 0;
}

这样,我们通过优化判断回文数的方式以及找到下一个回文数的规律,可以更快地找到第N个回文数,进一步降低时间复杂度。

加上高精度算法优化(是它)

要使用高精度算法优化,可以采用以下方法:

  • 定义一个高精度整数类,可以实现大整数的加法、减法和乘法等操作。
  • 在每次计算回文数时,将当前数字转化为高精度整数,进行高精度的加法操作,直到找到第N个回文数。
Code4(TLE 20)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;vector<int> add(vector<int>& a, vector<int>& b) {vector<int> res;int carry = 0;int n = max(a.size(), b.size());for (int i = 0; i < n; i++) {int sum = carry;if (i < a.size()) {sum += a[i];}if (i < b.size()) {sum += b[i];}res.push_back(sum % 10);carry = sum / 10;}if (carry) {res.push_back(carry);}return res;
}bool isPalindrome(vector<int>& num) {int n = num.size();for (int i = 0; i < n / 2; i++) {if (num[i] != num[n - 1 - i]) {return false;}}return true;
}vector<int> getNextPalindrome(vector<int>& num) {int carry = 1;int n = num.size();for (int i = 0; i < n; i++) {num[i] += carry;carry = num[i] / 10;num[i] %= 10;}if (carry) {num.push_back(carry);}return num;
}int main() {int T;cin >> T;for (int t = 0; t < T; t++) {vector<int> X;string str;cin >> str;for (int i = str.size() - 1; i >= 0; i--) {X.push_back(str[i] - '0');}int N;cin >> N;vector<int> ans = X;for (int i = 0; i < N; i++) {ans = getNextPalindrome(ans);while (!isPalindrome(ans)) {ans = getNextPalindrome(ans);}}for (int i = ans.size() - 1; i >= 0; i--) {cout << ans[i];}cout << endl;}return 0;
}
  • 注:该程序经本人改造。

优化++(还是它)

要进一步优化该程序,我们可以通过以下方式来提高效率:

  • 不需要每次都判断当前数是否是回文数,只需要在最后输出时判断即可。
  • 在计算下一个回文数时,可以直接从当前数一半开始倒序复制,这样可以减少循环次数。
Code5(RE 30)(加上高精度就AC了)
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;vector<int> tmp(1, 0);void initialize() {for (int i = 0; i < 20000; i++) {tmp.push_back(-1);}
}int sum(int x) {if (tmp[x] != -1) {return tmp[x];}if (x % 2 == 0) {tmp[x] = (pow(10, x / 2) - 1) / 9 * 2;}if (x % 2 == 1) {tmp[x] = sum(x + 1) - pow(10, x / 2);}return tmp[x];
}pair<int, int> count(int x) {x = (x + 8) / 9;int i = to_string(x).length() - 9;if (i < 1) {i = 1;}while (true) {if (sum(i) >= x) {return make_pair(i, 9 * sum(i - 1));}i++;}
}int solve(int x) {pair<int, int> result = count(x);int cnt = result.first;int sum = result.second;int half = pow(10, (cnt + 1) / 2 - 1) + (x - sum - 1);if (cnt % 2 == 1) {string halfStr = to_string(half);return stoi(halfStr.substr(0, halfStr.length() - 1) + string(halfStr.rbegin(), halfStr.rend()));} else {string halfStr = to_string(half);return stoi(halfStr + string(halfStr.rbegin(), halfStr.rend()));}
}int rev(int x) {int sz = to_string(x).length();int Sum = sum(sz - 1) * 9;Sum += stoi(to_string(x).substr(0, (sz + 1) / 2)) - pow(10, sz / 2 + sz % 2 - 1);while (solve(Sum) <= x) {Sum++;}return Sum - 1;
}int main() {initialize();int T;cin >> T;for (int i = 0; i < T; i++) {int N, X;cin >> N >> X;cout << solve(X + rev(N)) << endl;}return 0;
}

AC Code

//Code5加上高精度

我之所以不给代码是为了你们养成勤于动手的好习惯

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/621919.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

长亭科技-雷池WAF的安装与使用

目录 1、安装雷池 2、登录雷池 3、简单配置 4、防护测试 5、其他补充 1、安装雷池 在Linux系统上执行如下命令 &#xff08;需要docker环境&#xff0c;提前把docker、docker-compose 装好&#xff09; bash -c "$(curl -fsSLk https://waf-ce.chaitin.cn/release…

PHP常用符号和函数

// 单行注解 /* */ 多行注解 引号的使用 ’ ’ 单引号,没有任何意义,不经任何处理直接拿过来; ” “双引号,php动态处理然后输出,一般用于变量. 变量形态: 一种是True 即 真的; 另一种是False 即假的 常见变量形态: string 字串(数字\汉字\等等) integer 整数(1、2、…

【电源专题】案例:不同模块同一个管脚默认状态不一样会导致什么异常?

案例背景:在产品设计中,有时候会兼容两个不同供应商同一个方案的模块。比如两个供应商使用的内部方案都是一样的芯片,封装也是兼容的。但是由于专利、LAYOUT方便、软件开发方便等角度来看,可能会存在不同模块供应商的同一个PIN脚对应的芯片内部的管脚不一样。管脚不一样那么…

java基础知识点系列——分支语句(六)

java基础知识点系列——分支语句&#xff08;六&#xff09; 流程控制 流程控制语句分类 顺序结构分支结构循环结构 顺序结构 顺序结构是程序中最简单最基本的流程控制&#xff0c;没有特定的语法结构&#xff0c;按照代码的先后顺序&#xff0c;依次执行。 if语句 if语…

39岁学JAVA来得及吗?

39岁学JAVA来得及吗? 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Java的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;学习Java编…

五种嵌入式经典通信总线协议

一.先前知识 1.并行与串行 并行通信和串行通信是两种不同的数据传输方式&#xff1a; 并行通信&#xff1a;并行通信是指在同一时间使用多条并行传输的线路传输多个比特的数据。每个比特使用独立的线路进行传输&#xff0c;同时进行。这样可以在一个时钟周期内传输多个比特&…

螺纹钢负公差轧制中的测径仪应用

1、负公差轧制意义 为了满足生产使用要求&#xff0c;并根据轧制水平&#xff0c;在产品标准冲规定钢材尺寸的波动范围&#xff0c;允许钢材的实际尺寸与公称尺之间有一定的偏差&#xff0c;这个偏差一般称公差&#xff0c;公差分正、负公差&#xff0c;钢材按负公差轧制时&…

02.neuvector之Enforcer容器功能介绍

原文链接 一、功能介绍 Enforcer容器在neuvector中主要负责网络与DLP/WAF的规则策略的实现以及网络数据的采集上报&#xff1b; 以DaemonSet的方式运行&#xff0c;主要有三个进程monitor、agent、dp&#xff1b;进程分别主要职责如下&#xff1a; monitor&#xff1a;负责监…

[SpringAop + Logback +MDC] 现网必备全链路日志追踪

缘起&#xff1a;前几天有个粉丝私信&#xff0c;想了解现网环境如果出现问题&#xff0c;怎么快速定位。可能有些小伙伴这时候就会脱口而出&#xff0c;直接去看log 呗&#xff0c;有什么好说的。 但是&#xff0c;众所周知&#xff0c;后端服务面向的前端应用是多种多样的&am…

Shiro框架:Shiro登录认证流程源码解析

目录 1.用户登录认证流程 1.1 生成认证Token 1.2 用户登录认证 1.2.1 SecurityManager login流程解析 1.2.1.1 authenticate方法进行登录认证 1.2.1.1.1 单Realm认证 1.2.1.2 认证通过后创建登录用户对象 1.2.1.2.1 复制SubjectContext 1.2.1.2.2 对subjectContext设…

二、MySQL安装

目录 1、双击mysql8的安装向导 2、分为首次安装和再安装 1&#xff09;、首次安装 &#xff08;1&#xff09;如果是首次安装mysql系列的产品&#xff0c;需要先安装mysql产品的安装向导 &#xff08;2&#xff09;选择安装模式 2&#xff09;、不是首次安装 &#xff0…

学会这个技巧,制作电子杂志SOEASY

​电子杂志是一种非常流行的传播方式&#xff0c;它能够以更加生动、直观的方式展示你的品牌和产品。通过电子杂志&#xff0c;你可以将文字、图片、视频等多种元素有机地结合起来&#xff0c;创造出令人难忘的视觉效果。 如果你想制作一本电子杂志&#xff0c;但不知道从何入…

POSIX API与网络协议栈

本文介绍linux中与tcp网络通信相关的POSIX API&#xff0c;在每次调用的时候&#xff0c;网络协议栈会进行的操作与记录。 POSIX API Posix API&#xff0c;提供了统一的接口&#xff0c;使程序能得以在不同的系统上运行。简单来说不同的操作系统进行同一个活动&#xff0c;比…

QT上位机开发(进度条操作)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 进度条是一个比较常见的控件。如果某个操作需要很长的时间才能完成&#xff0c;那么这个时候最好有一个进度条提示&#xff0c;这样比较容易平复一…

18 串口通讯

文章目录 18.0 前言18.1 串口通讯协议简介18.1.1 物理层 18.2 RT1052 的 LPUART 简介18.3 UART 功能框图18.3.1 中断控制 18.4 UART 初始化结构体详解18.4.1 baudRate_Bps18.4.2 parityMode18.4.3 dataBitsCount18.4.4 isMsb18.4.5 stopBitCount18.4.6 txFifoWatermark与rxFifo…

JAVA开发入门

文章目录 计算机基本概念DOS常用命令JAVA语言发展史JDK下载JAVA体系与特点JDK安装JAVA环境变量配置 计算机基本概念 计算机组成原理 计算机组装 计算机&#xff1a;电子计算机&#xff0c;俗称电脑。是一种能够按照程序运行&#xff0c;自动、高速处理海量数据的现代化智能电子…

30天精通Nodejs--第十六天:express-快速入门

引言 接下来的几篇博客中,我们会深入浅出的介绍Nodejs的web框架:Express。 Express是Node.js生态中最受欢迎的Web应用框架之一,以其简洁、灵活和强大的中间件机制而闻名。它极大地简化了在Node.js中创建Web服务器及API的过程。本文将引导您通过几个简单的步骤,快速上手Exp…

MATLAB中simulink中scope同时显示两个输入信号

在使用scope时&#xff0c;需要两个输入信号的设置方法 1.点开scope图标 2 点击设置按钮&#xff0c; 然后弹出configuration properties&#xff1a;scope配置图&#xff0c;在Main选项下&#xff0c;在Number of input ports&#xff1a;1这里面更改数字&#xff0c;需要几…

什么是DDOS攻击?于自动化程度有哪些分类?

什么是DDOS攻击&#xff1f;DDOS攻击又称为分布式拒绝服务&#xff08;Distributed Denial of Service Attack&#xff09;&#xff0c;属于拒绝服务攻击中的高级手段&#xff0c;DDOS攻击可以在同一时间让多个计算机遭受到攻击&#xff0c;使攻击的目标无法正常使用&#xff0…

菜狗速递 快人一步

菜狗速递物流管理系统是一款针对网点管理人员开发的系统。 网点管理人员可以在该系统上进行员工信息的录入以及职能分配&#xff0c; 并能对客户的包裹进行一系列的处理&#xff0c;帮助客户查询订单信息&#xff0c;处理问题包裹等。 技术栈 基础框架&#xff1a;SpringBo…