删除不相加得到17的连续数字对后删除的数字数量

huangapple go评论113阅读模式
英文:

Count numbers deleted by removing consecutive digit pairs that don't sum to 17

问题

以下是我翻译好的内容:

问题陈述如下:

你会得到一个用十进制表示的数字,你必须通过选择两个连续的数字并删除它们来将其完全删除。但是这两个数字的和不应为17。我们称通过重复上述操作完全删除的数字为**“好数字”**。

示例:

  1. 9889 => 删除 88 得到 99
  2. 99 => 删除 99 以完全删除数字。
    结论:9889是好数字
    注意:我们不能删除 9889,因为这两个数字的和是 17

给定一个数字 N(偶数),你需要找到模 10^9 + 7 下的好数字的数量。在计数中也包括含有前导零的 N 位数。

测试案例:

案例1:

输入:2
输出:98

案例2:

输入:4
输出:9926

案例3:

输入:442
输出:417551213

我尝试过使用各种代码来解决这个问题,但无法获得结果。

英文:

Below is the problem statement that I have:

You get number written in base 10, you have to delete it completely by choosing two consecutive digits and deleting them. But the sum of those 2 digits should not be 17. We call the numbers which are fully deleted by repeating the above operation as "Good".

Example:

  1. 9889 => Delete 88 to get 99
  2. 99 => Delete 99 to fully delete number.
    Conclusion: 9889 is good.
    NOTE: We cannot remove 98 or 89 as the sum of these 2 digits is 17.

Given a number N(even) you want to find the number of good N-digit number modulo 10^9 + 7. Include in the count the N digit numbers containing leading zeros, too.

Test Cases:

Case 1:

  1. Input: 2
  2. Output: 98

Case 2:

  1. Input: 4
  2. Output: 9926

Case 3:

  1. Input: 442
  2. Output: 417551213

I have tried solving this using various codes but not able to get the result.

答案1

得分: 4

每个最后一个可能的错误状态序列,必然存在一个强制性序列生成了它。观察可能的通配符位置(当然,数字选择的位置最为关键),并尝试找出模式。

在以下示例中,为了对称起见,将9替换为8;x表示通配符:

输入长度为4,错误结果为9898:

  1. 9898

输入长度为4,错误结果为98:

  1. 989x
  2. 98x8
  3. 9x98
  4. x898

从上面的两个示例中,我们可以清楚地看出为什么会得到输出,即9926个好的4位数。

输入长度为6,错误结果为9898:

  1. 98989x
  2. 9898x8
  3. 989x98
  4. 98x898
  5. 9x9898
  6. x89898

输入长度为6,错误结果为9898或98:

  1. 9898xx
  2. 989xx8
  3. 98xx98
  4. 9xx898
  5. xx9898

输入长度为6,错误结果为98:

  1. 989x9x
  2. 98x8x8
  3. ...
  4. 9x989x
  5. ...

等等。

Python代码:

  1. # https://gist.github.com/rougier/ebe734dcc6f4ff450abf
  2. def binom(n,k):
  3. if not 0<=k<=n: return 0
  4. b=1
  5. for t in range(min(k,n-k)):
  6. b*=n; b//=t+1; n-=1
  7. return b
  8. def f(n):
  9. bads = 0
  10. for k in range((n - 2) // 2 + 1):
  11. bads += 9**k * binom(n, k)
  12. return (10**n - 2 * bads) % (10**9 + 7)
  13. print(f(442)) # 417551213

以上是翻译好的内容。

英文:

For each sequence of the last possible bad state, there must have been a forced sequence that generated it. Look at the locations of possible wild-cards (the digits that offer choice are the ones of interest, of course), and try to find a pattern.

In the following examples, for symmetry, switch 9s with 8s; xs are wildcards:

Input length 4, bad result 9898:

  1. 9898

Input length 4, bad result 98:

  1. 989x
  2. 98x8
  3. 9x98
  4. x898

We can clearly see from the two above why we get the output, 9926 good 4-digit numbers.

Input length 6, bad result 9898:

  1. 98989x
  2. 9898x8
  3. 989x98
  4. 98x898
  5. 9x9898
  6. x89898

Input length 6, bad result 9898 OR 98:

  1. 9898xx
  2. 989xx8
  3. 98xx98
  4. 9xx898
  5. xx9898

Input length 6, bad result 98:

  1. 989x9x
  2. 98x8x8
  3. ...
  4. 9x989x
  5. ...

etc.

Python code:

  1. # https://gist.github.com/rougier/ebe734dcc6f4ff450abf
  2. def binom(n,k):
  3. if not 0&lt;=k&lt;=n: return 0
  4. b=1
  5. for t in range(min(k,n-k)):
  6. b*=n; b//=t+1; n-=1
  7. return b
  8. def f(n):
  9. bads = 0
  10. for k in range((n - 2) // 2 + 1):
  11. bads += 9**k * binom(n, k)
  12. return (10**n - 2 * bads) % (10**9 + 7)
  13. print(f(442)) # 417551213

答案2

得分: 1

尝试使用树来尝试每个可能的解决方案。真正的问题是,你必须预测哪些数字将保留,以及是否可以在不产生17的情况下删除它们。例如,如果你有9823,你可以删除23,但是在末尾保留98将会阻塞你。

你可以尝试构建一棵树,其中每个分支都代表一种删除的可能性。如果所有分支都被阻塞,你将回到前一个节点。

英文:

Try with using a tree to try every possible solution. The real problem is that, you have to predict what digit will stay and if you can delete them without having a sum of 17.
For exemple, if you have 9823 you can delete 23 but you'll be blocked with 98 at the end.

You can try building a tree with every branch being a possibility of deletion. If all of the branches are blocked you get back to the previous node

答案3

得分: 0

不想暴露代码内容,但是判断一个数字是否好的问题可以通过“回溯法”来解决。

  1. solve(9889);
  2. public static void solve(int num) {
  3. try {
  4. solve(num, new LinkedList<>());
  5. System.out.println("未找到");
  6. } catch (FoundException fe) {
  7. System.out.printf("%d%n", num);
  8. fe.result.forEach(pair -> System.out.printf("-> %d,删除了 %d%n",
  9. pair.getKey(), pair.getValue()));
  10. }
  11. }
  12. private static class FoundException extends RuntimeException {
  13. public final List<Pair<Integer, Integer>> result;
  14. public FoundException(List<Pair<Integer, Integer>> result) {
  15. this.result = result;
  16. }
  17. }
  18. private static void solve(int num, LinkedList<Pair<Integer, Integer>> partialResult) {
  19. if (num == 0) {
  20. throw new FoundException(partialResult);
  21. }
  22. int tenPower = 1;
  23. while (num >= tenPower) {
  24. int n = num / tenPower;
  25. int del = n % 100;
  26. if (del % 10 + del / 10 != 17) {
  27. int n2 = (n / 100) * tenPower + (num % tenPower);
  28. partialResult.addLast(new Pair<>(n2, del));
  29. solve(n2, partialResult);
  30. partialResult.removeLast();
  31. }
  32. tenPower *= 10;
  33. }
  34. }
  35. 该问题似乎被构想成使用一个int”(31位无符号整数即可解决
  36. 因此我尝试使用int而不是数字列表进行操作
  37. 另一个特点使用异常将深层递归中的结果传递回顶层以获得正面结果传统方法是检查递归调用的结果
  38. **注意实际问题更具有数学性质**
英文:

Not wanting to spoil the coding, but whether a number is good, could be done with backtracking.

  1. solve(9889);
  2. public static void solve(int num) {
  3. try {
  4. solve(num, new LinkedList&lt;&gt;());
  5. System.out.println(&quot;Not found&quot;);
  6. } catch (FoundException fe) {
  7. System.out.printf(&quot;%d%n&quot;, num);
  8. fe.result.forEach(pair -&gt; System.out.printf(&quot;-&gt; %d, having deleted %d%n&quot;,
  9. pair.getKey(), pair.getValue()));
  10. }
  11. }
  12. private static class FoundException extends RuntimeException {
  13. public final List&lt;Pair&lt;Integer, Integer&gt;&gt; result;
  14. public FoundException(List&lt;Pair&lt;Integer, Integer&gt;&gt; result) {
  15. this.result = result;
  16. }
  17. }
  18. private static void solve(int num, LinkedList&lt;Pair&lt;Integer, Integer&gt;&gt; partialResult) {
  19. if (num == 0) {
  20. throw new FoundException(partialResult);
  21. }
  22. int tenPower = 1;
  23. while (num &gt;= tenPower) {
  24. int n = num / tenPower;
  25. int del = n % 100;
  26. if (del % 10 + del / 10 != 17) {
  27. int n2 = (n / 100) * tenPower + (num % tenPower);
  28. partialResult.addLast(new Pair&lt;&gt;(n2, del));
  29. solve(n2, partialResult);
  30. partialResult.removeLast();
  31. }
  32. tenPower *= 10;
  33. }
  34. }

The problem seems to be formulated such that an int (31 bits unsigned int) suffices.
Hence I tried working with int instead of a list of digits.

An other feature: using an exception to return from deep inside recursion to the top level with a positive result. The traditional way would be to check the result of a recursive call.

Note: the actual problem is a more mathematical one.

huangapple
  • 本文由 发表于 2020年10月8日 22:47:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/64265080.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定