[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\)
寫一個程式,給定一個\(N\)(\(2 \le N \le 10,N=16\))進位制數\(M\)(\(100\)位之內),求最少經過幾步可以得到迴文數。如果在\(30\)步以內(包含\(30\)步)不可能得到迴文數,則輸出Impossible
!
輸入格式
兩行,分別是\(N,M\)。
輸出格式
STEP=ans
輸入輸出樣例
輸入 #1
10
87
輸出 #1
STEP=4
分析
一道不錯的模擬題。
回顧一下題面,程式框架應該是這樣:
- 輸入
m
- 判斷
m
是否迴文,如果是,輸出次數並退出 - 將
m
和m
的倒序相加,儲存到m
中 - 還沒到
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_c
和c_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_c
和c_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.