任何人都可以指导我一个算法/公式,说明如何计算具有某个上限的数字和的所有变化
因此,例如,如果我的数字总和为6且上限为123,则该数字总和的所有变化将为: 6,15,24,33,42,51,60,105,114和123。
上限最高可达10 ** 18,程序需要在1秒内完成(以C / CPP计算),因此无法选择暴力。
答案 0 :(得分:1)
我认为有一种递归方法可以解决这个问题:考虑一个过程int f(bool limit, int bit_count, int bit_sum)
,它计算不超过bit_count
位的变量数,这些位的总和为{{1} }}。 bool参数bit_sum
表示限制(在您的示例中为123)是否生效。
假设limit
表示限制的第i位。
Limit[i]
在您的位总和为6且上限为123的示例中,int f(bool limit, int bit_count, int bit_sum){
if(bit_sum < 0)
return 0;
if(bit_count == -1)
if(bit_sum == 0)
return 1;
else
return 0;
int ans = 0;
for(int i = 0; i <= limit ? Limit[bit_count] : 9; i++){
ans += f(limit && i == Limit[bit_count], bit_count - 1, bit_sum - i);
}
return ans;
}
,Limit[2] = 1
,Limit[1] = 2
。答案是Limit[0] = 3
。
为了快速起见,您可以通过记录表将此递归方法转换为动态编程方法。相应DP方法的时间复杂度为f(true, 2, 6)
。我认为这个速度可以满足你的1秒要求。
答案 1 :(得分:1)
创建基于DP的解决方案,以计算总和为n的最多k个数字的总和。
F(k,n)= sum_i F(k-1,n-i)
假设您的最大值有k位数,最高位数是sig(最大值),而dropig(最大值)是没有最高位数的数字。
对于i,G(k,max,n)= F(k-1,n)+ G(k-1,drops(最大),n-sig(max))+ sum_i(k-1,ni) = 1到sig(max)-1。
显然,你必须处理角落案件。但这是摘要。
第一个组件对应于数字长度小于最大数字长度的情况。
第二个组成部分对应于最高有效数字的解与最大有效数字相同的情况。
第三个组成部分对应于解决方案的最高有效数字小于最大有效数字但大于或等于1的情况。