问题是找到A和B之间的数字计数(包括),其数字总和等于S.
同时在A和B之间打印最小的这个数字(含).
输入:
单线由A,B,S组成.
输出:
两行.
在第一行中,A和B之间的整数数,其总和等于S.
在第二行中,A和B之间的最小数字.
约束:
1 <= A <= B <10 ^ 15
1 <= S <= 135
来源:黑客地球
我的解决方案仅适用于30个输入.什么是最好的解决方案呢?
我现在使用的算法现在计算最小数字的总和,然后在十位数的每次改变时再次计算总和.以下是Python中的解决方案:
def sum(n):
if (n<10):return n
return n%10 + sum(n/10)
stri = raw_input()
min = 99999
stri = stri.split(" ")
a= long (stri[0])
b= long (stri[1])
s= long (stri[2])
count= 0
su = sum(a)
while a<=b :
if (a % 10 == 0 ):
su = sum(a)
print a
if ( s == su):
count+=1
if (a<= min):
min=a
a+=1
su+=1
print count
print min
Run Code Online (Sandbox Code Playgroud)
tem*_*def 10
这里有两个不同的问题:找到具有正确数字总和的数字之间的最小数字,并找到具有该数字总和的范围内的数值.我将分别讨论这些问题.
解决此问题的一般方法如下:
为此,我们应该能够使用动态编程方法.我们将尝试回答以下形式的查询:
有多少个D位数字,其第一个数字是k,其数字总和为S?
我们将创建一个表N [D,k,S]来保存这些值.我们知道D最多将是16,而S最多将是136,所以这个表只有10×16×136 = 21,760个条目,这也不算太糟糕.为了填写它,我们可以使用以下基本情况:
然后,我们可以使用以下逻辑来填写其他表条目:
这表示总和为S的第一个数字为k的(D + 1) - 数字的数量由总和到S-k的D位数的数量给出.总和到S-k的D位数的数量由总和到S-k的D位数的数量给出,其第一个数字是0,1,2,...,9,所以我们有总结一下.
填写此DP表只需要时间O(1),事实上,如果您真的关心时间,可以想象它会预先计算并将其硬编码到程序中.
那我们怎么用这个表呢?好吧,假设我们想知道总和到S的数量是多少或等于某个数字X.为此,我们可以一次处理一个X的数字.让我们一次写一个X作为d 1 ... d n.我们可以从N [n,d 1,S]开始.这给出了n位数的数字,其第一个数字是d 1,总计为S.这可能高估了小于或等于X的值的数量,这些数值总和为S.例如,如果我们的数字是21,111并且我们想要总和精确到12的值的数量,然后查找这个表值将给出我们误差的数字,如29,100,以2开头,长度为5位,但仍然大于X.要处理这个,我们可以移动到数字X的下一个数字.由于第一个数字是2,数字中的其余数字必须总计为10.此外,由于X(21,111)的下一个数字是1,我们现在可以从总数中减去从2个,3个,4个,5个,...,9开始的4位数字的数量,加起来为10.我们可以一次重复这个过程一个数字.
更一般地,我们的算法如下.设X为我们的数字,S为目标总和.写X = d 1 d 2 ... d n并计算以下内容:
# Begin by starting with all numbers whose first digit is less than d[1].
# Those count as well.
result = 0
for i from 0 to d[1]:
result += N[n, i, S]
# Now, exclude everything whose first digit is d[1] that is too large.
S -= d[1]
for i = 2 to n:
for j = d[i] to 8:
result -= N[n, d[i], S]
S -= d[i]
Run Code Online (Sandbox Code Playgroud)
然后,值result将是小于或等于X的值的数量,其总和精确为S.此算法最多只运行16次迭代,因此它应该非常快.此外,使用此算法和较早的减法技巧,我们可以使用它来计算A和B之间有多少值总和到S.
我们可以在我们的DP表中使用类似的技巧来找到大于A的数字的最小数字,该数字总和恰好是S.我将把细节留作练习,但作为提示,一次只能工作一个数字,试图找到DP表返回非零值的最小数字.
希望这可以帮助!