问题描述
题目描述
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
例如:给定一个十进制数 56,将 56 加 65(即把 5656 从右向左读),得到 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 为最少得到回文数的步数。
否则输出 Impossible!。
输入输出样例
输入
10
87
输出
STEP=4
解题思路
本问题需要解决的是要求输入数字与其逆序排列的数字相加在30次内可以得到一个对称的数字(回文数),判断输入数字以及相加时候的数字是否为回文数,进行N进制的数据的加减(本身利用各个进制的加法实现),通过递归实现string和int字符的转换来辅助加减,记录递归的次数,并判断在30次内是否可以实现;
解题方案
用string字符存储输入数据M,通过递归形式实现string和int之间的转换,没有很好的解决N进制问题,单纯利用进制加减过于复杂
源代码
#include#include #include #include using namespace std; //老师,剩下进制的加法运算好复杂,我只实现了二进制和十进制,其他的也能实现就是很复杂 // 是不是我的思路错了,应该有更简洁的算法吧 //string转换成int int inreverse(string str) { int n; stringstream stream; stream << str; stream >> n; return n; } //int转换为string string streverse(int n) { string str; stringstream stream; stream << n; stream >> str; return str; } //判断是否为回文数 int isrecycle(string str) { string str1 = str; reverse(str1.begin(), str1.end()); if (str.compare(str1)==0) { return 0; //两字符相等; } else return 1; //不是回文数; } //二进制加法 int add2(int a, int b) { int re = a; while (b) { int tmp = a; a = a ^ b; b = (tmp & b) << 1; re = a; } return re; } //回文数算法 int elem10(string str, int &step,int m) { int s = inreverse(str); reverse(str.begin(), str.end()); int d = inreverse(str); int n = 0; switch (m) { case 10: n = s + d; break; case 2: n = add2(s, d); break; default: break; } string s2 = streverse(n); //cout << s2 << endl; if (int ret = isrecycle(s2) == 0) { return step + 1; } else { elem10(s2, step,m); step++; } return step+1; } int main() { int a; string s; int step = 0; cout << "请输入几进制数N(N=2,8,16,10):" << endl; cin >> a; cout << "请输入进制数M:" << endl; cin >> s; if (int ret = isrecycle(s) == 0) { cout << "step=" << step << endl; } else { cout << "step=" << elem10(s, step, a) << endl; } return 0; }
解题正解
主要优化了N进制计算上
#include#include #include #include using namespace std; int n,ans; string str; vector s1,s2; int main() { cin>>n; cin>>str; for(int i=0;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 =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="<
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)