PAT甲级1010. Radix (25)
题意:
给定一对正整数,例如6和110,这个等式6 = 110可以是真的吗?答案是“是”,如果6是十进制数,110是二进制数。
现在对于任何一对正整数N1和N2,你的任务是找到一个数字的基数,而另一个数字的基数。
输入规格:
每个输入文件包含一个测试用例。每个案例占用一个包含4个正整数的行:
N1 N2标签基数
这里N1和N2每个不超过10位数。数字小于其基数,并从集合{0-9,a-z}中选择,其中0-9表示十进制数0-9,a-z表示十进制数10-35。
如果“标签”为1,最后一个数字“radix”为N1的基数,如果“tag”为2,则为N2。
输出规格:
对于每个测试用例,以一行打印另一个数字的基数,使得方程式N1 = N2为真。如果方程不可能,打印“不可能”。如果解决方案不是唯一的,输出最小可能的基数。
思路:
就是给你两个数,已知其中一个数的进制,然后求另外一个数是多少进制就可以让两个数相等。
暴力遍历会在测试点7超时。 二分搜索后,如果不考虑溢出会在测试点10报错。
二分搜索查找进制,下界是n2中最大的一个数字 + 1;上界是n1的10进制数 + 1;别的没有什么坑点感觉。
ac代码:
C++
// pat1010_radix.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<iostream> #include<cstdio> #include<string> #include<algorithm> #include<queue> #include<vector> #include<unordered_map> #include<cmath> using namespace std; int main() { string n1, n2; int tag, radix; cin >> n1 >> n2 >> tag >> radix; long long a = 0, b = 0,res; if (tag == 2) swap(n1, n2); char ch; int index = 0; while (!n1.empty()) { ch = n1.back(); if (ch >= 'a' && ch <= 'z') { a += (ch - 'a' + 10) * pow(radix, index); } else { a += (ch - '0') * pow(radix, index); } n1.pop_back(); index++; } long long temp = 0; for (int i = 0; i < n2.length(); i++) { if (n2[i] > temp) temp = n2[i]; } if (temp >= 97) temp -= 87; else temp -= 48; long long left = temp + 1; long long right = a + 1; res = a + 2; while(left <= right) { temp = (left + right) / 2; index = 0; b = 0; string tempn2 = n2; while (!tempn2.empty()) { ch = tempn2.back(); if (ch >= 'a' && ch <= 'z') { b += (ch - 'a' + 10) * pow(temp, index); } else { b += (ch - '0') * pow(temp, index); } tempn2.pop_back(); index++; if (b > a || b < 0) break; } if (a == b) { res = min(res, temp); right--; } else if (b > a || b < 0) { right = temp - 1; } else if (b < a) { left = temp + 1; } } if (res == a + 2) cout << "Impossible" << endl; else cout << res << endl; return 0; }
来源:https://www.cnblogs.com/weedboy/p/7244819.html