1. 程式人生 > 其它 >[luogu p1015] 迴文數

[luogu p1015] 迴文數

技術標籤:c++python程式語言windows演算法

傳送門

題面

題面描述

若一個數(首位不為零)從左向右讀與從右向左讀都一樣,我們就將其稱之為迴文數。

例如:給定一個十進位制數\(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 \le N \le 10,N=16\))進位制數\(M\)(\(100\)位之內),求最少經過幾步可以得到迴文數。如果在\(30\)步以內(包含\(30\)步)不可能得到迴文數,則輸出Impossible!

輸入格式

兩行,分別是\(N,M\)

輸出格式

STEP=ans

輸入輸出樣例

輸入 #1

10
87

輸出 #1

STEP=4

分析

一道不錯的模擬題。
回顧一下題面,程式框架應該是這樣:

  1. 輸入m
  2. 判斷m是否迴文,如果是,輸出次數並退出
  3. mm的倒序相加,儲存到m
  4. 還沒到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_cc_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_cc_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.