2021.3.30.每日" 一"题
-PTA第一题"十六进制转换为八进制"
出题人:孙佳萌
思路
方法可以为十六进制转换为十进制,十进制再转换为八进制
也可以为十六进制转换为二进制,二进制再转换为八进制
#include<iostream> // 转二进制做法
#include<string>
using namespace std;
int main() {
string s1, s2;
cin >> s1;
if (s1 == "0") {
cout << 0;
}
else {
s2 = "";//二进制
for (int j = 0; j < s1.length(); j++) {
switch (s1[j]) {//将十六进制转为二进制
case '0':
s2 += "0000";
break;
case '1':
s2 += "0001";
break;
case '2':
s2 += "0010";
break;
case '3':
s2 += "0011";
break;
case '4':
s2 += "0100";
break;
case '5':
s2 += "0101";
break;
case '6':
s2 += "0110";
break;
case '7':
s2 += "0111";
break;
case '8':
s2 += "1000";
break;
case '9':
s2 += "1001";
break;
case 'A':
s2 += "1010";
break;
case 'a':
s2 += "1010";
break;
case 'B':
s2 += "1011";
break;
case 'b':
s2 += "1011";
break;
case 'C':
s2 += "1100";
break;
case 'c':
s2 += "1100";
break;
case 'D':
s2 += "1101";
break;
case 'd':
s2 += "1101";
break;
case 'E':
s2 += "1110";
break;
case 'e':
s2 += "1110";
break;
case 'F':
s2 += "1111";
break;
case 'f':
s2 += "1111";
break;
default:
break;
}
}
//要转为8进制,必须是3的倍数,若不满足条件,则补0
if (s2.length() % 3 == 1)
s2 = "00" + s2;
if (s2.length() % 3 == 2)
s2 = "0" + s2;
int flag = 0;
for (int k = 0; k < s2.length() - 2; k += 3) {//三位为一个单位
int p = 4 * (s2[k] - '0') + 2 * (s2[k + 1] - '0') + s2[k + 2] - '0';
if (p) //去前导0
flag = 1;
if (flag)
cout << p;
}
cout << endl;
}
return 0;
}
//
// 转十进制方法
#include <iostream>
using namespace std;
int main()
{
string s;
cin >> s;
int ans = 0,sum=1;
for (int i=0;i<s.size();i++) {
if (s[i] >= '0' && s[i] <= '9') ans = ans*16 + s[i] - '0';
else if (s[i] >= 'A' && s[i] <= 'Z') {
ans = ans*16+s[i]-'A'+10;
}
else {
ans = ans*16+s[i]-'a'+10;
}
}
cout << oct << ans; // 十进制转八进制方法与上述类似,笔者在此偷个懒
return 0;
}
补充
有同学可能会想到直接接收十六进制类型的数据,然后输出八进制类型的数据,这样很简单,但是只要能这样做的题,都极少会出现在竞赛中,所以该方法了解即可,还是要掌握上述代码转换的方法.
-PTA第二题"IP地址转换"
出题人:张一帆
差异
和上题不同的是,本题更偏向于字符串的使用,读取字符串后,从左到右开始扫描,每8个字符转换一次数据,因题目给出的是二进制数据,所以灵活运用位运算可以使代码更加简洁.
#include <iostream>
using namespace std;
string s; // 声明一个字符串
int dp[4],flag; // 储存转换后的数据
int main()
{
cin >> s;
for (int i=0;i<s.size();i++) {
if (s[i] == '1') dp[flag] |= 1; // 如果改字符为1,则使该数二进制下的第一位变为1
dp[flag] <<= 1; // 另该数左移一位
if ((i+1)%8 == 0) dp[flag] >>= 1,flag++; // 如果满足此条件,则表示已扫描过了8个字符,因为之前dp[flag]会向左多移一位,所以此时向右移一位
}
for (int i=0;i<4;i++) { // 输出结果
cout << dp[i];
if (i != 3) cout << ".";
}
return 0;
}
补充
如果之前没有接触过位运算,又或者是位运算不熟练,可以自己根据数据多演算几遍,明白位运算的原理.
ACWING"快速幂" https://www.acwing.com/problem/content/91/
方法分为两种,迭代法和递归法,原地址的题解介绍的很充分