牛牛选择了一个正整数X,然后把它写在黑板上。然后每一天他会擦掉当前数字的最后一位,直到他擦掉所有数位。 在整个过程中,牛牛会把所有在黑板上出现过的数字记录下来,然后求出他们的总和sum.
例如X = 509, 在黑板上出现过的数字依次是509, 50, 5, 他们的和就是564.
牛牛现在给出一个sum,牛牛想让你求出一个正整数X经过上述过程的结果是sum.
输入包括正整数sum(1 ≤ sum ≤ 10^18)
输出一个正整数,即满足条件的X,如果没有这样的X,输出-1。
564
509
def get_sum(x): temp = 0 while x != 0: temp += x x = int(x/10) return temp sum = int(input()) l = 0 r = sum mid = 0 for i in range(55): mid = int((l+r)/2) if get_sum(mid) == sum: print(mid) exit() elif get_sum(mid) < sum: l = mid else: r = mid l = get_sum(l) r = get_sum(r) if l == sum or r == sum: if l == sum: print(l) else: print(r) else: print(-1)
def lucky(n): if len(n)==1: return n number=int(n) select='' k = len(n) for i in range(k,0,-1): select+=str(number//(int('1'*i))) number=number%int('1'*i) if int(select)<int(n): return int(select) else: return -1 while True: try: n=input() print(lucky(n)) except: break
#通过分析可以知道sum/(1+1/9)<x<=sum,然后遍历就是,但是这样只能过90%。 #所以可以优化下右边界,如果已经超过了sum,后面也就不用继续搜索了 n=int(input()) def slove(n): s=int(n/(1.0+1.0/9)) e=n+1 i=s for i in range(s,e): k=i ans=0 while k>0: ans+=k k=k//10 if ans==n: return i elif ans>n: return -1 print(slove(n))
看评论都是说用二分法。我怎么就没想到呢?貌似我用的是“十分法”哈哈。
提供一种极为简单易懂的思路:
就拿题目的564举例:
我们要找到一个数x,经过一系列擦掉最后一位操作后,和为564。
首先要确定x的位数,它一定是三位或两位(如果是四位,结果肯定是四位)。在此我们就假定它是三位数abc(就算最终结果是两位数,那么求出来a=0就可以了)。经过一系列擦操作之后:abc + ab + a = 564,
即:(a * 100 + b * 10 + c) + (a * 10 + b) + (a) =564;
即 :111 * a + 11 * b + 1 * c = 564
我们想要求a、b、c,很简单,a = 564 // 111 = 5("//"表示取整操作)
此时564 - 111 * 5 = 9。接下来要求b:b = 9//11 = 0
此时 9 - 0 * 11 = 9。接下来要求c:c = 9//1 = 9
最终结果5->0->9
扩展到四位数x,它的形式一定是1111 * a + 111 * b + 11 * c + 1* d = x
同理扩展到n位数。
根据上面的思路,代码就简单了:
string = input()
num, res = int(string), ""
for i in range(len(string), 0, -1):
res += str(num // int(i * "1"))
num = num % int(i * "1")
print(res if int(res) < int(string) else -1)
如果判断找不到x呢,如果求出来结果比输入的数大,肯定是不对的,此时输出-1