2058. 笨拙的手指 - AcWing题库
奶牛贝茜正在学习如何在不同进制之间转换数字。
但是她总是犯错误,因为她无法轻易的用两个前蹄握住笔。
每当贝茜将数字转换为一个新的进制并写下结果时,她总是将其中的某一位数字写错。
例如,如果她将数字 14 转换为二进制数,那么正确的结果应为 1110,但她可能会写下 0110或 1111。
贝茜不会额外添加或删除数字,但是可能会由于写错数字的原因,写下包含前导 0 的数字。
给定贝茜将数字 N 转换为二进制数字以及三进制数字的结果,请确定 N 的正确初始值(十进制表示)。
输入格式
第一行包含 N 的二进制表示,其中一位是错误的。
第二行包含 N 的三进制表示,其中一位是错误的。
输出格式
输出正确的 N 的值。
数据范围
0≤N≤10^9,且存在唯一解。
输入样例:
1010
212
输出样例:
14
样例解释
14 在二进制下的正确表示为 1110,在三进制下的正确表示为 112。
思路:
1. 输入数据
2. 进制转换
3. 枚举二进制修改每一位的值 记录到哈希表
4. 枚举三进制修改每一位的值 注意三进制修改有两种情况 并查看哈希表种是否存在 存在则输出
Code:
#include <stdio.h>
#include <string.h>
#define N 103
char s1[30], s2[30]; //存储二进制和三进制
int h[N]; //根据数据范围 最多30位数 所以找一个2-3倍的数组
int find(int x){ //哈希表
int t = x % N;
while (h[t] != -1 && h[t] != x){
if(++t == N) t = 0; //找到一个空位 或者 当前值是查找的值是退出
}
return t; //返回找到的点
}
int base(char *str, int x){ //x进制转换为十进制
int res = 0, len = strlen(str);
int i;
for(i = 0; i < len; i++){
res = res * x + str[i] - '0';
}
return res;
}
int main(){
memset(h, -1, sizeof(h));
scanf("%s", s1);
scanf("%s", s2);
int i;
for(i = 0; i < strlen(s1); i++){ //将每一位进行修正 二进制的30位就可以表示数据范围
int x;
char s[30];
strcpy(s, s1); //临时字符串
s[i] ^= 1; //修改当前位的数字
if(strlen(s) > 1 && s[0] == '0') continue; //非0的字符且含有前导零 排除
x = base(s, 2); //将二进制字符串转换为10进制
h[find(x)] = x; //将该十进制存入哈希表 并将值设置为该十进制
}
for(i = 0; i < strlen(s2); i++){
int j, x;
for(j = 0; j < 3; j ++){
if(s2[i] != j+'0'){ //对三进制的数进行修改 有两种情况 排除本身
char s[30];
strcpy(s, s2);
s[i] = j + '0'; //修改当前位的数字
if(strlen(s) > 1 && s[0] == '0') continue;
x = base(s, 3);
if(h[find(x)] == x) printf("%d\n", x); //如果当前的数字在哈希表中存在则输出
}
}
}
return 0;
}