京东笔试题——进制均值

1. 题目描述

  尽管是一个CS专业的学生,小B的数学基础很好并对数值计算有着特别的兴趣,喜欢用计算机程序来解决数学问题,现在,她正在玩一个数值变换的游戏。她发现计算机中经常用不同的进制表示一个数,如十进制数123表达为16进制时只包含两位数7、11(B),用八进制表示为三位数1、7、3,按不同进制表达时,各个位数的和也不同,如上述例子中十六进制和八进制中各位数的和分别是18和11,。 小B感兴趣的是,一个数A如果按2到A-1进制表达时,各个位数之和的均值是多少?她希望你能帮她解决这个问题? 所有的计算均基于十进制进行,结果也用十进制表示为不可约简的分数形式。

2. 题目分析

  题目很长,这大概就是笔试题的特点,墨迹一堆,就看你能不能理解。大概的意思就是给你一个整数N,让你将N分别转化为2进制、3进制……N-1进制,然后把每一位的数字相加,对这几种进制求均值。假设T(N,X)为将整数N转化为X进制后的各位数字和,则Answer = [T(N,X=2)+T(N,X=3)+……+T(N,X=N-1)] / (N-1-1)。

3. ac解法——cpp

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;

// 求整数x转换成n进制后各位数字的和
int everyByteSum(int x, int n, int &everysum) {
    int yushu = x % n;
    everysum += yushu;
    if (x/n >= n) {
        everyByteSum(x/n, n, everysum);
    }
    else {
        everysum += x/n;
    }
    return everysum;
}

int main() {
    int X;
    cin >> X;

    if (X < 1 || X > 5000) // 判定非法输入
        return -1;

    int everysum = 0;
    int allsum = 0;

    for(int i = 2; i < X; i++) { // 计算每一种进制的总和
        everysum = 0;
        allsum += everyByteSum(X, i, everysum);
    }

    string ans; // 答案要求输出分数形式,所以使用字符串
    int len = X - 2;

    // 进行分式化简
    if (allsum % len == 0) {
        allsum = allsum / len;
        len = 1;
    }
    for(int i = 2; i <= len; i++) {
        while(allsum%i == 0 && len%i == 0 && allsum/i!=0 && len/i!=0){
            allsum = allsum / i;
            len = len / i;
        }
    }

    // 将结果转化为分式后输出
    ans = to_string(allsum);
    ans += "/";
    ans += to_string(len);
    cout << ans << endl;
    return 0;
}

4. 总结

  在这里分式化简的部分不够有普遍适用性。理论上应该先求取allsum和len的最大公约数之后,分别除掉最大公约数即可。在规定时间内时间有点紧张,一时掀不起来求最大公约数的算法,所以采用了上面化简的不优美的方法。所以在这里贴一下求最大公约数的算法,希望下次需要的时候能够信手拈来。
  最大公约数的求取:
方法一:辗转相除法

int MaxCommonDivisor(int a, int b) {
    if (a % b == 0)
        return b;
    else
        return MaxCommonDivisor(b, a%b);
}

方法二:辗转相减法

int MaxCommonDivisor(int a, int b) {
    if (a == b)
        return a;
    if (a > b)
        return MaxCommonDivisor(a-b, b);
    else
        return MaxCommonDivisor(a, b-a);
}

方法三:暴力求解(如题目解答中化解部分)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值