题目
奶牛贝茜正在学习如何在不同进制之间转换数字。
但是她总是犯错误,因为她无法轻易的用两个前蹄握住笔。
每当贝茜将数字转换为一个新的进制并写下结果时,她总是将其中的某一位数字写错。
例如,如果她将数字 14 转换为二进制数,那么正确的结果应为 1110,但她可能会写下 0110 或 1111。
贝茜不会额外添加或删除数字,但是可能会由于写错数字的原因,写下包含前导 0 的数字。
给定贝茜将数字 N 转换为二进制数字以及三进制数字的结果,请确定 N 的正确初始值(十进制表示)。
输入格式
第一行包含 N 的二进制表示,其中一位是错误的。
第二行包含 N 的三进制表示,其中一位是错误的。
输出格式
输出正确的 N 的值。
数据范围
0≤N≤10^9,且存在唯一解。
输入样例:
1010
212
输出样例:
14
样例解释
14 在二进制下的正确表示为 1110,在三进制下的正确表示为 112。
解题思路
分析
首先该题的数据范围为 0 ≤ N ≤ 109,当 N 取到 109时
二进制数为 111011100110101100101000000000
三进制数为 2120200200021010001
所以将二进制每一位枚举并更改最多只需要枚举 30 次
将三进制每一位枚举并更改最多只需要枚举 2*19 次
可见时间复杂度并不高
所以只需要先将二进制数每一位依次更改,并转成十进制数,存入 Set 中,表示该数可以通过二进制数更改一位得来
再将三进制数的每一位依次更改,若更改到某一位得到的十进制数可以通过二进制更改一位得来,则符合题意,该十进制数即为所求
秦九韶算法
m 进制数转 10 进制数:
X = xnmn + xn-1mn-1 + … + x0m0(xi = 0,1,…,m-1)
X = m(m(…(mxn) + x1) + x0
例如:
1010(B)
1*2^3 + 0*2^2 + 1*2^1 + 0*2^0 = 2*(2*(2*1 + 0) + 1) + 0 = 10
详细的介绍可以去网上看看,这边只做一个了解
Java(手写秦九韶算法)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.LinkedHashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out);
char[] b = in.readLine().toCharArray(); // 二进制数
char[] t = in.readLine().toCharArray(); // 三进制数
Set<Integer> set = new LinkedHashSet<Integer>(); // 存储所有能由二进制数更改一位得到的十进制数
for(int i = 0; i < b.length; i++) {
b[i] ^= 1; // 更改一位
int x = nToTen(b, 2); // 获取更改一位后的十进制数
set.add(x); // 记录可以生成的十进制数
b[i] ^= 1; // 复原
}
for(int i = 0; i < t.length; i++) {
char temp = t[i];
for(int j = 0; j < 3; j++) {
if(t[i] - 48 != j) {
t[i] = (char) (j + 48); // 更改一位
int x = nToTen(t, 3); // 将三进制数转换成十进制数
if(set.contains(x)) { // 判断该数能否由二进制数更改一位获得
out.println(x);
out.flush();
return;
}
}
t[i] = temp; // 复原
}
}
in.close();
}
/**
* 将 n 进制数转换成 10 进制数
* @param ch 要转换的的数
* @param n 原来数的进制
* @return
*/
public static int nToTen(char[] ch, int n) {
int x = 0;
// 秦九韶算法
for(int i = 0; i < ch.length; i++) x = n * x + (ch[i] - 48);
return x;
}
}
Java(使用Integer.valueOf())
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.LinkedHashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out);
char[] b = in.readLine().toCharArray();
char[] t = in.readLine().toCharArray();
Set<Integer> set = new LinkedHashSet<Integer>();
for(int i = 0; i < b.length; i++) {
b[i] ^= 1;
int x = Integer.valueOf(new String(b), 2);
set.add(x);
b[i] ^= 1;
}
for(int i = 0; i < t.length; i++) {
char temp = t[i];
for(int j = 0; j < 3; j++) {
if(t[i] - 48 != j) {
t[i] = (char) (j + 48);
int x = Integer.valueOf(new String(t), 3);
if(set.contains(x)) {
out.println(x);
out.flush();
return;
}
}
t[i] = temp;
}
}
in.close();
}
}
C++
#include<iostream>
#include<unordered_set>
using namespace std;
// 将 n 进制数转换成 10 进制数
int nToTen(string s, int n)
{
int x = 0;
// 秦九韶算法
for(char c : s) x = n * x + (c - 48);
return x;
}
int main()
{
std::ios::sync_with_stdio(false);
string b; // 二进制数
string t; // 三进制数
std::unordered_set<int> h; // 存储更改二进制数其中一位后生成的十进制数
cin >> b >> t;
// '&'对原数组进行操作
for(char &c : b)
{
c ^= 1; // 更改一位
int x = nToTen(b, 2); // 将二进制数转换成十进制数
h.insert(x); // 记录该十进制数
c ^= 1; // 复原
}
for(char &c : t)
{
char temp = c;
for(int i = 0; i < 3; i++)
{
if(temp - 48 != i)
{
c = i + 48; // 更改一位
int x = nToTen(t, 3); // 将三进制数转换成十进制数
if(h.count(x)) // 判断该十进制数能否由之前的二进制数更改一位得到
{
cout << x << endl;
return 0;
}
}
}
c = temp; // 复原
}
}