tags
数学
贪心
中文题面
题目描述
亚历山大正在学习如何把十进制数字转换成其他进制,但是他不懂英文字母,所以他只是把数值按照十进制数字的方式写出来。这意味着他会用 10 代替英文字母 A。这样,他就会把十进制的 475 转换成十六进制的 11311(475=1·162+13·161+11·16^0)。亚历山大平静的生活着,直到有一天他试着把这些数字转换回十进制数字。
亚历山大记着他总是用较小的数字工作,所以他需要找到在 n 进制的基础下,用他的转换系统得出数字 k 的最小十进制数。
输入输出格式
输入格式:
第一行是一个正整数 n ( 2<=n<=10^9),第二行有一个正整数 k ,满足数字 k中包含不超过 60 个数值。第二行整数中的没每一个数字都严格小于 n。
亚历山大保证答案存在且不超过 10^18,数字 k 不含前导 0.
输出格式:
输出一个数字 x —— 问题的答案。
样例 #1
样例输入 #1
13
12
样例输出 #1
12
样例 #2
样例输入 #2
16
11311
样例输出 #2
475
样例 #3
样例输入 #3
20
999
样例输出 #3
3789
样例 #4
样例输入 #4
17
2016
样例输出 #4
594
思路
我们假设n=13,如56、12、19、87这样的数我们统称为AB形式,显然有AB (实际计算中是10A + B)* 13^0 < A * 13^1 + B * 13^0,那么我们可以确定一个贪心思路就是尽可能累积到足够大的数再乘以当前位的base转十进制
代码
// Edit by Mr_Way
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, base = 1, now = 0, len, nowbase = 1, the, res = 0, last = -1, emp = 1;
string k;
unordered_map<int, int> mp;
signed main() {
cin >> n >> k;
len = k.length();
for (int i = 0; i < len; i++) {
if (k[i] - '0' == 0) mp[i] = last;
else last = i;
}
for (int i = len - 1; i >= 0; i--) {
the = k[i] - '0';
if (the == 0 && !emp) {
if ((k[mp[i]] - '0') * pow(10, i - mp[i]) * nowbase + now < n) {
nowbase *= 10;
continue;
}
res += now * base, base *= n;
nowbase = 10;
now = the;
}
else if (now + the * nowbase < n) {emp = false, now += the * nowbase, nowbase *= 10;}
else {
res += now * base, base *= n;
nowbase = 10;
now = the;
}
}
res += now * base, base *= n;
cout << res;
return 0;
}