从数字到0最快的方法

时间:2019-06-05 15:02:42

标签: c++ algorithm

所以,我有这样的作业:

给出两个数字nk可以达到long long的限制,我们执行以下操作:

  • 如果n = n / kn整除,请分配k
  • 如果n无法被1整除,则n减少k

查找从n0的最少操作数。

这是我的解决方法

#define ll long long

ll smallestSteps(ll n, ll k) {
    int steps = 0;
    if (n < k) return n;
    else if (n == k) return 2;
    else {
        while (n != 0) {
            if (n % k == 0) {
                n /= k;
                steps++;
            }
            else {
                n--;
                steps++;
            }
        }
        return (ll)steps;
    }
}

我认为这个解决方案是O(n/k)

但是我认为nk可能非常大,因此程序可能会超过1s的时间限制。有更好的方法吗?

编辑1:我使用ll使其更短

2 个答案:

答案 0 :(得分:8)

鉴于以下几点,可以对算法进行改进:

  1. 如果n<k,则k|(n-m)永远不会保持正m。因此答案是n个步骤。
  2. 如果(k|n)不成立,则m, m<n的最大数量为n - (n%k)。因此,需要n%k个步骤,直到(k | m)再次成立。

实际上,您所需要做的就是继续使用std::div对余数进行除法(或依靠编译器进行优化),并将步数增加余数+1。

steps=0
while(n>0)
     mod = n%k
     n = n/k
     steps+=mod + 1
return steps

答案 1 :(得分:1)

这可以通过更简单的主程序来完成。

n转换为基础k。令d为该数字中的位数。 要达到0,您需要除以k (d-1)倍。 您减去1的次数就是该数字的数字总和。

例如,考虑n = 314,k = 3。

以3为底的

314为102122。这有6位数字;数字总和为8。 您将有6-1 + 8步...到0的13步。

使用您的C ++程序包将其转换为新的基数,将数字转换为整数,然后对数组求和。这会将所有移位计数工作推入模块方法。

请确保这不适用于k的怪异值,但是您也可以窃取可用的转换包,而不必编写自己的转换包。