[luogu p1015] 回文数

传送门

题面

题面描述

若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。

例如:给定一个十进制数\(56\),将\(56\)加\(65\)(即把\(56\)从右向左读),得到\(121\)是一个回文数。

又如:对于十进制数\(87\):

STEP1:\(87+78 = 165\)
STEP2:\(165+561 = 726\)
STEP3:\(726+627 = 1353\)
STEP4:\(1353+3531\) = \(4884\)

在这里的一步是指进行了一次\(N\)进制的加法,上例最少用了\(4\)步得到回文数\(4884\)。

写一个程序,给定一个\(N\)(\(2 \le N \le 10,N=16\))进制数\(M\)(\(100\)位之内),求最少经过几步可以得到回文数。如果在\(30\)步以内(包含\(30\)步)不可能得到回文数,则输出Impossible!

输入格式

两行,分别是\(N,M\)。

输出格式

STEP=ans

输入输出样例

输入 #1

10
87

输出 #1

STEP=4

分析

一道不错的模拟题。
回顾一下题面,程序框架应该是这样:

  1. 输入m
  2. 判断m是否回文,如果是,输出次数并退出
  3. mm的倒序相加,存储到m
  4. 还没到30次?返回第二步。到了?输出impossible并返回

但是,对于一个100位的整数,我们需要用字符串存入。
那么接下来我们要解决一些问题:

如何判断一个数是否回文?

C++STL是其臭名昭著的很大的优势,这不,string就提供了reverse函数。(其实string有很多优点,但美中不足的是他必须用臭名昭著的cin读入。)

string a;
string tmp=reverse(a.begin(),a.end());
if(tmp==a) ....

如何进行加法?

高精度是个好东西。
关于更多高精度的知识,请自行搜索。

string add(string a,string b)
{
    int numa[105],numb[105],numc[105];
    int len=a.length(),lenc;
    string ret;
    for(int i=0;i<len;i++)
    {
        numa[len-i]=c_to_i(a[i]);
        numb[len-i]=c_to_i(b[i]);
    }
    int d=0;
    for(lenc=1;lenc<=len;lenc++)
    {
        numc[lenc]=numa[lenc]+numb[lenc]+d;
        d=numc[lenc]/10;
        numc[lenc]%=10;
    }
    numc[lenc]=d;
    while(!numc[lenc]) lenc--;
    for(int i=lenc;i;i--)
        ret+=i_to_c(numc[i]);
    return ret;
} 

注:以上代码中的i_to_cc_to_i代表整数转字符和字符转整数。

关于进制

本题其实无必要转进制,只要改一下高精度就可以,把进位部分改成:

    for(lenc=1;lenc<=len;lenc++)
    {
        numc[lenc]=numa[lenc]+numb[lenc]+d;
        d=numc[lenc]/k;
        numc[lenc]%=k;
    }

k是我定义的进制。
并且在i_to_cc_to_i函数中要加上对16进制的特殊处理。下面是这两个函数的定义:

int c_to_i(char a)
{
    if(isdigit(a)) return a-'0';
    return a-'A'+10;
}

char i_to_c(int a)
{
    if(a<10) return a+'0';
    return a-10+'A';
}

解决了这几个问题,代码就简单了。

代码

#include <bits/stdc++.h>
using namespace std;
y1
string s;
int n;

string my_reverse(string a)
{
    string tmp=a;
    reverse(tmp.begin(),tmp.end());
    return tmp;
}

bool valid(string a)
{
    return a==my_reverse(a);
} 

int c_to_i(char a)
{
    if(isdigit(a)) return a-'0';
    return a-'A'+10;
}

char i_to_c(int a)
{
    if(a<10) return a+'0';
    return a-10+'A';
}

string add(string a,string b,int k)
{
    int numa[105],numb[105],numc[105];
    int len=a.length(),lenc;
    string ret;
    for(int i=0;i<len;i++)
    {
        numa[len-i]=c_to_i(a[i]);
        numb[len-i]=c_to_i(b[i]);
    }
    int d=0;
    for(lenc=1;lenc<=len;lenc++)
    {
        numc[lenc]=numa[lenc]+numb[lenc]+d;
        d=numc[lenc]/k;
        numc[lenc]%=k;
    }
    numc[lenc]=d;
    while(!numc[lenc]) lenc--;
    for(int i=lenc;i;i--)
        ret+=i_to_c(numc[i]);
    return ret;
} 

int main()
{
    cin>>n>>s;
    for(int i=0;i<=30;i++)
    {
        if(!valid(s)) s=add(s,my_reverse(s),n);
        else
        {
            printf("STEP=%d\n",i);
            return 0;
        }
    }
    printf("Impossible!\n");
    return 0;
}

哦对了,这里特别提醒一个地方,高精度里的一个微小的部分:int d=0;
你看到他了吗?我当初是这么写的:int d;
由于这个变量在函数内,所以不会自动初始化为0,就因为这个点,我要WA到自闭。

S选手就算了,J选手请特别留意:
这个小问题在Windows环境下测不出来
在此感谢

评测记录:
给了链接自行看吧

over.

原文地址:https://www.cnblogs.com/crab-in-the-northeast/p/luogu-p1015.html

时间: 2024-10-09 09:51:41

[luogu p1015] 回文数的相关文章

洛谷 P1015 回文数

P1015 回文数 标签 字符串 模拟 NOIp普及组 1999 云端 难度 普及- 时空限制 1s / 128MB 题目描述 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数. 例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数. 又如:对于10进制数87: STEP1:87+78 = 165 STEP2:165+561 = 726 STEP3:726+627 = 1353 STEP4:1353+3531 = 4884 在这里的一

P1015 回文数

P1015 回文数 题目描述 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数. 例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数. 又如:对于10进制数87: STEP1:87+78 = 165 STEP2:165+561 = 726 STEP3:726+627 = 1353 STEP4:1353+3531 = 4884 在这里的一步是指进行了一次N进制的加法,上例最少用了4步得到回文数4884. 写一个程序,给定一个N(2<=

洛谷 P1015 回文数 Label:续命模拟QAQ

题目描述 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数. 例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数. 又如:对于10进制数87: STEP1:87+78 = 165 STEP2:165+561 = 726 STEP3:726+627 = 1353 STEP4:1353+3531 = 4884 在这里的一步是指进行了一次N进制的加法,上例最少用了4步得到回文数4884. 写一个程序,给定一个N(2<=N<=10,N=1

luogu_2425【题解】小红帽的回文数 (基本算法)

题目:https://www.luogu.org/problemnew/show/P2425 大意:求 t 个数,a[1.....t]  满足其在 x 进制下是回文数,求x. 题解: 1.可以枚举x,求出.(不知道可不可以). 2.当 x 大于sqrt(a) 时,数字会只有两位数. 所以设 i 为两位数的分别的数字. 有 i * x + i == a 化简 x= a / i - 1 所以 i 大于 sqrt(a),且当 i 是 a 的因数时,右边就是答案. 当 i 小于 sqrt(a) 时,枚举

判断一个数是否为回文数

#include <stdio.h> int is_palindromic(int num) {  char _old = num;  char _new = 0;  while (num)  {   _new = _new * 10 + (num % 10);   num = num / 10;  }  if (_new == _old)  {   return 1;  }  else  {   return 0;  } } int main() {  int num = 0;  scanf

LeetCode 9 Palindrome Number (回文数)

翻译 确定一个整数是否是回文数.不能使用额外的空间. 一些提示: 负数能不能是回文数呢?(比如,-1) 如果你想将整数转换成字符串,但要注意限制使用额外的空间. 你也可以考虑翻转一个整数. 然而,如果你已经解决了问题"翻转整数(译者注:LeetCode 第七题), 那么你应该知道翻转的整数可能会造成溢出. 你将如何处理这种情况? 这是一个解决该问题更通用的方法. 原文 Determine whether an integer is a palindrome. Do this without ex

要求循环输入一个数,判断是否为回文数

import java.util.Scanner; public class HuiWenShu { public static void main(String[] args) { Scanner input = new Scanner(System.in); char c = 'y'; //初始化c为y,为下面的循环做好准备 while(c == 'y'){ while(c == 'y'){ System.out.println("请随意输入一个大于三位的奇位数"); //回文数属

回文数 第N个回文数

判断回文数还是不难,如果能转为字符串就更简单了. 如果是求第N个回文数呢. 12321是一个回文数,这里先考虑一半的情况. 回文数的个数其实是有规律的.如: 1位回文数: 9个 2位回文数: 9个 3位回文数: 90个 4位回文数: 90个 5位回文数: 900个 6位回文数: 900个 … 我们看到9.90.900,是不是很有规律,那是什么原因?很简单,我们把回文数拆开两半 [123321]来看.两半的变化一样的,那我们只算其中一半就行了.首位不能是0,所以左半最小为 100,最大为999,共

Palindrome Number (回文数)

回文数是指这样的数字:正读和倒读都是一样的.如:595,2332都是回文数,234不是回文数. 注意:负数不是回文数 Determine whether an integer is a palindrome. Do this without extra space. Some hints: Could negative integers be palindromes? (ie, -1) If you are thinking of converting the integer to string