牛客竞赛语法入门班函数与递归习题—[NOIP1999]回文数

题目描述:

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

例如:给定一个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>10时,使用大写'A'字母表示10,'B'表示11,...,'E'表示16

输入描述:

两行,分别为N,M

输出描述:

STEP=ans

输入

9
87

输出

STEP=6

解题思路:

  1. 一维数组存储数据

  2. 回文数判断

  3. 加法运算处理

详细讲解:

        对于数据存储这块,long long 的范围是-9223372036854775808~9223372036854775807,题目所述N进制的M在100位之内,很显然long long是放不下M的,考虑到后续需要实现加法运算和进位处理,所以此处使用一维数组的形式存储数据,每个数组放置一个位数,例如N = 9,M=123,a[0] = 1,a[1] = 2,a[2] = 3;

 

        根据回文数的特点,回文数个数为奇数个时,除了最中间的那位数以外,第1位数与倒数1位数相等,第2位数与倒数第2位数相等...以此类推,我们只要使用两个指针i和j分别指向数组头和数组尾,逐个判断直至数组长度的一半即可。

 

        加法运算处理这块稍微麻烦一点,在进行加法的过程中需要考虑不同进制的加法。那么在此处就需要读者需要不同进制加法的基础知识,例如,9进制下87+78的结果是多少?2进制下100+001的结果是多少?对于任何进制N下的数a和数b相加的结果范围在[0,2N-1],将他们相加的数使用if进行判断,大于等于N则需要进位,此处使用CF代表进位(CF == 1 则进位,CF == 0 则不需要进位),在下一位的两个数相加之前将CF加上即可。

        注意:10~15的数表示成A~F,在输入时根据ASCII码进行处理转换。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MA = 1e7+7;
ll ans = 0,len;
ll N;
ll a[MA];//使用数组存储各个位数
//回文数判断
bool judge(){
    ll i = 0,j = len - 1;
    while(i != len/2){
        if(a[i++] != a[j--])
            return false;
    }
    return true;
}
//N进制加法处理
void addnumber(){
    ans++;
    ll i=0,j=len-1;
    //按题目所述步骤加法得到每一位
    while(i !=len/2){
        ll num = a[i] + a[j];
        a[i++] = num,a[j--] = num;
    }
    //防止奇数个数位
    if(len % 2==1)
        a[i] = 2*a[i];
    //进位处理
    ll CF = 0;
    for(int k=0;k<len;k++){
        ll nb;
        //判断上一位是否需要进位
        nb = a[k] + CF;
        //该位数是否有进位
        if(nb >= N)
            CF = 1,nb -= N;
        else
            CF = 0;
        //更新
        a[k] = nb;
    }
    //判断最后一位是否需要进位
    if(CF)
        a[len++] = 1; 
}
int main(){
    cin >> N;
    string S;
    cin >> S;
    //将数字均放入a数组中
    for(int i=0;i<S.length();i++){
        if(S[i] >= 48 && S[i] <= 57)
            a[i] = S[i]-48;
        else
            a[i] = S[i]-55;
    }
    len = S.length();
    while(!judge() && ans <= 30)
        addnumber();
    if(ans <= 30)
        cout << "STEP=" << ans << endl;
    else
        cout << "Impossible!" << endl; 
    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值