• [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)步得到回文数(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
    ",i);
    			return 0;
    		}
    	}
    	printf("Impossible!
    ");
    	return 0;
    }
    

    哦对了,这里特别提醒一个地方,高精度里的一个微小的部分:int d=0;
    你看到他了吗?我当初是这么写的:int d;
    由于这个变量在函数内,所以不会自动初始化为0,就因为这个点,我要WA到自闭。

    S选手就算了,J选手请特别留意:
    这个小问题在Windows环境下测不出来
    在此感谢

    评测记录:
    给了链接自行看吧

    over.

  • 相关阅读:
    iphone:URL initWithString 返回为空
    android:unable to instantiate activity componentinfo
    android:进度条
    android:spinner
    android:DDMS查看Threads
    android:ListView:convertView.setTag()来设置数据
    iphone:使用UIImagePickerController从IPhone照片库或照相机获取图像
    android:ListView中的getView原理
    android 从assets和res中读取文件
    android:menu.xml
  • 原文地址:https://www.cnblogs.com/crab-in-the-northeast/p/luogu-p1015.html
Copyright © 2020-2023  润新知