xtuoj Digit String
题目

思路
首先,我们需要将得到的字符串,按字符拆解,将字符转换为对应数字。
如何做呢?通常只需以字符串的形式读入,然后计算字符串的长度(int len=strlen(s)),这是为了看有多少位字符需要处理,接着我们用一个 for 循环遍历这些字符,如果是 '0' - '9' ,那么将字符的 '0' - '9',减去 '0',即可得到数字的0-9,如果是 'A' - ' F',那么减去 'A',会得到数字0-5,但是我们需要字符'A' - ' F',表示的是10-15,所以我们再原来减去 'A' 的同时再加上10,这样就把字符全部转换为对应的数字了。
题目要求我们找出最小的进制表示的字符串,使得对应的十进制等于 n,所以我们需要先找出最小能够表示我们字符串的进制,接着再去判断其对应的十进制下是否等于 n,如果不等,那我们进制就要增大。
k 进制下的每一位数字都满足 < k,如果有数字 >= k,那么该进制无法表示该字符串,所以我们只需要保证最大的数字 < k,即可保证所有数字都 < k,那么至少保证了该进制表示下是有效的。所以最小可能的进制为最大数字+1,因为进制肯定是整数。
接着,我们再去判断最小可能的进制下,对应的十进制是否等于 n,如果不等,那么该进制不是最小能够满足条件的进制,其实这里我们可以优化一下,因为计算对应的十进制是诸位进行的,那么当我们计算到某位的时候,表示的十进制已经超过了 n,那么该进制肯定不会等于 n 了,因为所有的数字非负,只会不减;那么我们继续增大最小进制,继续上述判断。所以这里我们肯定要采用两个标记变量,比如说 valid 和 found,valid 用来标记当前进制是否有效,found 用来判断是否存在某进制使得对应下的十进制等于 n。
现在还有个问题没有解决,那么就是如何将 k 进制转换为10进制。这里我们采用的方法是多项式法,就是比如 k 进制下是123,那么转换为十进制,就是3*k^0+2*k^1+1*k^2。
现在如果是手算我们解决了,但是代码怎么实现呢?我们刚开始处理的字符串是由高位到低位存到一个数字里面,比如说是字符串123,存到数组里面就是digit[]=[1,2,3],假设 value 就是我们转换到十进制后的值,先初始化为0,3*k^0+2*k^1+1*k^2 = 3+(2+(1+0*k)*k)*k,我们可以把计算式写成右边迭代的形式,就可以发现规律啦,我们先从内部算起,首先我们计算value*k+digit[0],接着我们把这个结果赋值给value,然后又是value*k+digit[1],还是赋值给value,接着计算value*k+digit[2],也就是说value=value*k+digit[i],我们从将 digit 遍历完后的结果value,也就是我们要求解的值。
以上就把所有问题解决啦,大家可以试试自己看着这个思路写写代码,可以先不看我的代码哟!
代码
#include <stdio.h>
#include <string.h>int main() {char str[32];int n;while (scanf("%s %d", str, &n) != EOF) {int len = strlen(str);int max_digit = 0;int digits[32];for (int i = 0; i < len; i++) {if (str[i] >= '0' && str[i] <= '9') {digits[i] = str[i] - '0';} else if (str[i] >= 'A' && str[i] <= 'F') {digits[i] = str[i] - 'A' + 10;}if (digits[i] > max_digit) {max_digit = digits[i];}}int min_base = (max_digit + 1) > 2 ? (max_digit + 1) : 2;if (min_base > 16) {printf("Impossible\n");continue;}int found = 0;for (int k = min_base; k <= 16; k++) {long long value = 0;int valid = 1;for (int i = 0; i < len; i++) {value = value * k + digits[i];if (value > n) {valid=0;break;}}if (valid && value == n) {printf("%d\n", k);found = 1;break;}}if (!found) {printf("Impossible\n");}}return 0;
}代码二
稍微改了一下,可以思考为什么也是对的。
#include <stdio.h>
#include <string.h>int main() {char str[32];int n;while (scanf("%s %d", str, &n) != EOF) {int len = strlen(str);int max_digit = 0;int digits[32];for (int i = 0; i < len; i++) {if (str[i] >= '0' && str[i] <= '9') {digits[i] = str[i] - '0';} else if (str[i] >= 'A' && str[i] <= 'F') {digits[i] = str[i] - 'A' + 10;}if (digits[i] > max_digit) {max_digit = digits[i];}}int min_base = (max_digit + 1) > 2 ? (max_digit + 1) : 2;if (min_base > 16) {printf("Impossible\n");continue;}int found = 0;for (int k = min_base; k <= 16; k++) {long long value = 0;int valid = 1;for (int i = 0&&valid; i < len; i++) {value = value * k + digits[i];if (value > n) valid=0;}if (valid && value == n) {printf("%d\n", k);found = 1;break;}}if (!found) {printf("Impossible\n");}}return 0;
}代码三
这个加了一部分,也改了一部分,同样可以去思考原因。
#include <stdio.h>
#include <string.h>int main() {char str[32];int n;while (scanf("%s %d", str, &n) != EOF) {int len = strlen(str);int max_digit = 0;int digits[32];for (int i = 0; i < len; i++) {if (str[i] >= '0' && str[i] <= '9') {digits[i] = str[i] - '0';} else if (str[i] >= 'A' && str[i] <= 'F') {digits[i] = str[i] - 'A' + 10;}if (digits[i] > max_digit) {max_digit = digits[i];}}int min_base = (max_digit + 1) > 2 ? (max_digit + 1) : 2;if (min_base > 16) {printf("Impossible\n");continue;}int found = 0;for (int k = min_base; k <= 16; k++) {long long value = 0;int valid = 1;for (int i = 0; i < len; i++) {if (digits[i] >= k) {valid = 0;break;}value = value * k + digits[i];if (value > n) {break;}}if (valid && value == n) {printf("%d\n", k);found = 1;break;}}if (!found) {printf("Impossible\n");}}return 0;
}