MYOJ_1214:(洛谷P1015)[NOIP 1999 普及组]回文数(高精度计算与数制结合运用)

注:本题在不同的OJ输出格式不同,请多多注意!!!!!!!!!!!!!!!!!!!!!! 

题目描述

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

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

输入

两行,分别是 N,M。

输出

如果能在 30 步以内得到回文数,输出格式形如 STEP=ans,其中 ans 为最少得到回文数的步数。

样例输入输出 

输入:                    输出:

10                           STEP=4
87

思路:

高精,通过进制转换来判断是否回文。

STEP 1:声明进制、高精数组及输入字符串。

STEP 2:定义用于将字符串形式的数字转换为高精数组形式的函数tonum,处理方式如下:

  • 如果是数字字符('0'-'9'),转换为对应的数值。

  • 如果是字母字符('A'-'Z'),转换为对应的数值(10-35)。

STEP 3:定义函数用于生成数字的反序表示,就是一个逆序存放,我觉得不用多讲的

STEP 4:高精加法,懂的都懂

STEP 5:判断高精数是否回文,方法是遍历数组的前半部分,比较对应位置的数字是否相等,如果全部相等,返回true;否则返回false

STEP 6:输入,tonum()将读入字符串转为高精数组,进行迭代,isPalin()检查是否回文,是就输出当前次数并结束,否则生成a的反序数组b,ab相加,结果存回a。…… 30次后,输出impossible

代码(标注释的是在洛谷提交的)
#include<bits/stdc++.h>
using namespace std;
#define N 105
int n,a[N],b[N];
char s[N];
void tonum(char*s,int*a)
{
    int len=strlen(s);
    for(int i=1;i<=len;i++)
    {
        if(s[len-i]>='0'&&s[len-i]<='9')
        {
        	a[i]=s[len-i]-'0';
		}
        else
        {
        	a[i]=s[len-i]-'A'+10;
		}
    }
    a[0]=len;
}
void genOpp(int*a,int*b)
{
    for(int i=1;i<=a[0];i++)
    {
    	b[i]=a[a[0]+1-i];
	}
    b[0]=a[0];
}
void addToA(int*a,int*b)
{
    int c=0; 
    for(int i=1;i<=a[0]||i<=b[0];i++)
    {
        a[i]+=b[i]+c; 
        c=a[i]/n;
        a[i]%=n;
    }
    if(c>0)
    {
    	a[++a[0]]=c;
	}
}
bool isPalin(int*a)
{
    for(int i=1;i<=a[0]/2;i++)
    {
        if(a[i]!=a[a[0]-i+1])
        {
        	return false;
		}
    }
    return true;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
    cin>>n>>s;
    tonum(s,a);
    for(int i=0;i<=30;i++)
    {
        if(isPalin(a))
        {
            cout/*<<"STEP="*/<<i;
            return 0;
        }
        genOpp(a,b);
        addToA(a,b);
    }
    cout<<"Impossible";
//	cout<<"Impossible!";
    return 0;
}

运行结果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值