luogu 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<=N<=10,N=16)进制数M(100位之内),求最少经过几步可以得到回文数。如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible!”

输入输出格式

输入格式:

 

两行,分别是N,M。

 

输出格式:

 

STEP=ans

 

输入输出样例

输入样例#1:
10
87
输出样例#1:
STEP=4

思路:

  算法:无脑模拟

  若当前的m不是回文串,则对m进行操作,ans++,直到m变成回文串为止

坑点:

  需要特殊处理n==10或n==16的情况

上代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;

LL n,m;
char s[102];

bool pd(LL a) {
    LL l=1,r=1; //左右端点 
    while(l<=a) l*=n;
    l/=n;
    for(; l>=r; l/=n,r*=n) 
        if((a/l)%n!=(a/r)%n) return false;
    return true;
}

LL f(LL a) { //翻转 
    LL ret=0,l=1,now=1; //now枚举每位上的数字,到达该位及后面的数,所需要乘的数 
    while(l<=a) l*=n; //l为左端点 
    l/=n; 
    for(; now<=a; l/=n,now*=n) ret+=now*((a/l)%n);
    return ret;
}

int main() {
    scanf("%lld",&n);
    if(n==10) scanf("%lld",&m);
    else {
        scanf("%s",&s);
        LL tmp=0,now=1,len=strlen(s)-1;
        if(n<10) {
            for(int i=len; i>=0; i--) {
                tmp+=now*(s[i]-'0');
                now*=n;
            }
        }
        else if(n==16) {
            for(int i=len; i>=0; i--) {
                if(s[i]>='0' && s[i]<='9') tmp+=now*(s[i]-'0');
                else tmp+=now*(s[i]-'A'+10); //A~F
                now*=n;
            }
        }
        m=tmp;
    }
    LL step=0;
    while((!pd(m)) && step<=30) {
        step++; 
        m+=f(m); //change
    }
    if(step<=30) printf("STEP=%lld\n",step);
    else printf("Impossible!\n");
    return 0;
}

 

posted @ 2017-10-22 12:28  夜雨声不烦  阅读(272)  评论(0编辑  收藏  举报