学习笔记,仅供参考,希望各位大佬纠错。
链接1:
https://ac.nowcoder.com/acm/contest/20960/1008
题意1:
给出 10 个数码的出现次数,0 到 9 的出现次数均小于 10,找到一个由这些数码组成的最小的数,该数是回文数且不能有前导 0。
代码1:
#include
#include
using namespace std;
int main(void)
{
int x;
string ans, mid;
for (int i = 0; i <= 9; i++)
{
cin >> x;
if (x & 1) mid += ('0' + i);
for (int j = 1; j <= x / 2; j++) ans += ('0' + i);
}
if (mid.size() > 1) puts("-1");
else
{
int index = 0;
while (index < ans.size() && ans[index] == '0') index++;
if (index == ans.size() && index != 0) puts("-1");
else
{
swap(ans[index], ans[0]);
cout << ans << mid;
reverse(ans.begin(), ans.end());
cout << ans << endl;
}
}
return 0;
}
解释1:
回文数的数位可以是奇数,mid 就是用来存储中间位的数,所以 mid 的长度不能大于 1 ,否则就不能构成回文数。因此先判断 x 是否为奇数,是奇数就从中拿出一个存在 mid 中。
x & 1:& 是按位与,该式可用来判断 x 是否为奇数,即与 1 进行与运算,如果 x 二进制最后一位是 1 ,那么结果为 1 ,否则为 0 。
mid += ( '0' + i ):字符型与整数相加,等于字符 0 的 ASCII 码加上 i 后的 ASCII值所对应的字符。
ans 是用来存储回文数对称的一半,故循环时 x 要取一半,因此后面程序有输出 mid 中间位后再输出倒置的 ans。
ans += ( '0' + i ):字符相加运算是把字符连接起来。
ans 中会有前导 0,此时分两种情况讨论,一是 ans 中全是 0,即 index == ans.size ( ) 且 index != 0 时,是没有回文数的;二是 ans 中不全为 0,那么就要进行换位,将最后一个 0 后面的数( ans [ index ])与首位(ans [ 0 ])交换。
若ans 中没有前导 0,那么直接进入 else 语句,符合的条件是 index != ans.size () 并且 index == 0,正因如此,所以 else 前面的 if 语句条件要再设置一个条件 index != 0,因 index 为 0,swap 函数执行无意义。
总结1:
代码是借鉴别人的代码改了一些些,第一次看题目,没有一点思绪,无从下手,后面看别人代码时也看不太懂,然后通过问老师、调试、上网找资料才略懂一点,耗时是比较长的。但是,其中暴露出很多问题,是值得自己深思和改正的。最后想说,算法真不好学,需要花时间,有足够的耐心,得迎难而上。一道题可能要花好长时间写出代码,又要花好长时间调试代码,最后真正解决完这道题的时间可能花了很久很久,期间心情都被整 emo 了。但这也是学习的过程,对于我们小白来说,就是慢慢来,一步步进阶,脚踏实地。" 既然选择了远方,便只顾风雨兼程 ",一起共勉。
链接2:
https://ac.nowcoder.com/acm/contest/20960/1009
题意2:
一个N( 2 <= N <= 10 或 N = 16)进制数 M(100位之内),不断地将它与它的反序数(即将整数的数字倒过来形成的整数)相加,求最少经过几步可以得到回文数,步数要小于 30,否则就输出 " Impossible! "。
代码2:
#include
using namespace std;
int main()
{
int n;
string a;
cin >> n >> a;
int l = a.size();
long long res = 0;
for(int i = 0;i < l;i ++)
if(a[i] <= '9')
res = res*n + a[i] - '0';
else res = res*n + a[i] - 'A' + 10;
bool f = 0;
for(int i = 0;i < 31;i ++){
long long k = res;
long long d = 0;
while(k){
d = d*n + k%n;
k /= n;
}
if(d == res){
f = 1;
cout << "STEP=" << i << endl;
break;
}
res += d;
}
if(!f)
cout << "Impossible!" << endl;
return 0;
}
解释2:
将 n 进制数转换成10进制数,以下部分代码可实现该转换:
for(int i = 0;i < l;i ++){
if(a[i] <= '9')
res = res*n + a[i] - '0';
else res = res*n + a[i] - 'A' + 10;
}
将该数先以字符型表示,从它的首位开始取,拿 9 进制下的 87 为例有:res = ( 8 * 9 + 7 ) * 9^0 = = 79,即有九进制数 87 的十进制数为 79。
将 10 进制下的数转换成 n 进制下的反序数,输出的数是十进制的,由以下部分代码实现:
while(k){
d = d*n + k%n;
k /= n;
}
九进制数 87 的反序数是 78,其用十进制表示为 7*9 + 8 = 71,将 k = 79 代入得 d = 71,又如:
要顺利通过该题,res 的数据类型还得定为 long long。
总结2:
就这个代码,我硬是冥思苦想都不得其解,卡住一处语句上了,可能就是菜的缘故。不过呢,还是得给自己点个赞的,格物致知精神可嘉。就从上面的那个代码中,仅靠自己的理解,会收获一些新知识,不过最后完全理解还是得请大佬赐教,由此又收获了更多的知识。所以说有时还是得不懂就问,靠别人来指点迷津,而不是自己死磕,有时候不划算,耗时还毁好心情,人都给整 emo 了。算法路虽艰辛,但贵在坚持,所以,hold on!一起共勉。