洛谷P1015 [NOIP1999 普及組] 回文數
題目描述
若一個數(首位不為零)從左向右讀與從右向左讀都一樣,我們就將其稱之為回文數。
例如:給定一個十進制數 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 \leq N \leq 10\) 或 N=16)進制數 M(100 位之內),求最少經過幾步可以得到回文數。如果在 30 步以內(包含 30 步)不可能得到回文數,則輸出 Impossible!
。
輸入格式
兩行,分別是 N ,M。
輸出格式
如果能在 30 步以內得到回文數,輸出格式形如 STEP=ans
,其中 ans 為最少得到回文數的步數。
否則輸出 Impossible!
。
輸入輸出樣例
輸入 #1
10
87
輸出 #1
STEP=4
題目分析
回文數不用多說,反轉后判等。需要注意的有兩點,一是本題允許多種進制,二是M的范圍可以達到100位,顯然要用到高精度了。
解題思路
首先利用字符串接收數字。對字符串進行遍歷將其每一位轉換為整型數進行存儲,這里需要注意的是16進制要區分字母大小寫。利用reverse函數實現反轉操作。執行相加操作前,首先要判斷第一次輸入的原數是不是回文數,如果是那么ans為0,程序結束。執行高精度加法時,具體進位邏輯見代碼,需注意的是我們執行的是一個數和它的倒序相加,所以向前或向后進位對本題無影響。
代碼
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int n,ans;
string str;
vector<int> s1,s2;
int main()
{
cin>>n;
cin>>str;
for(int i=0;i<str.length();i++) //將字符串表示的數字每一位轉換為整形進行存儲
{
if(str[i]>='0'&&str[i]<='9')
s1.push_back(str[i]-'0');
else
if(str[i]>='A') //十六進制需注意字母大小寫
s1.push_back(str[i]-'A'+10);
else
s1.push_back(str[i]-'a'+10);
}
s2=s1;
reverse(s1.begin(),s1.end()); //反轉函數
if(s1==s2)
{
cout<<"STEP=0";
return 0;
}
while(++ans<=30) //計數
{
int len=s1.size();
for(int i=0;i<len;i++) //高精度加法
{
s1[i]+=s2[i]; //對應位相加
if(s1[i]>=n) //某一位大於n時需進行進位操作
{
if(i!=len-1) s1[i+1]++; //每次最多進1,這里由於兩數互相倒序,向前進位與向后進位對本題無影響
else s1.push_back(1); //當最后一位滿n,進位需要多申請一個位置進位
}
s1[i]%=n; //進位后留下余數
}
s2=s1;
reverse(s1.begin(),s1.end());
if(s1==s2)
{
cout<<"STEP="<<ans;
return 0;
}
}
cout<<"Impossible!";
return 0;
}