所以,我有这样的作业:
给出两个数字n
和k
可以达到long long
的限制,我们执行以下操作:
n = n / k
被n
整除,请分配k
n
无法被1
整除,则n
减少k
查找从n
到0
的最少操作数。
这是我的解决方法
#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)
?
但是我认为n
和k
可能非常大,因此程序可能会超过1s的时间限制。有更好的方法吗?
编辑1:我使用ll
使其更短
答案 0 :(得分:8)
鉴于以下几点,可以对算法进行改进:
n<k
,则k|(n-m)
永远不会保持正m。因此答案是n
个步骤。(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
的怪异值,但是您也可以窃取可用的转换包,而不必编写自己的转换包。