919B |第n个数字总和为10 |代码部队

Posted

技术标签:

【中文标题】919B |第n个数字总和为10 |代码部队【英文标题】:919B | nth Numbers having digit sum as 10 | Codeforces 【发布时间】:2020-05-02 15:39:25 【问题描述】:

这是question 的链接。本质上,它要求找到数字总和为 10 的 kth 数字。我尝试了多种解决方案,并在线查看了解决方案。特别是这个one(也在下面分享)。具有恒定时间的人谈论算术级数中的异常值,并使用它找到总和为 10 的 nth 数字。显然,代码不正确,因为它在 k=1000 等时测试用例失败。

#include <bits/stdc++.h> 

using namespace std; 

int findNth(int n) 
 
    int nthElement = 19 + (n - 1) * 9; 
    int outliersCount = (int)log10(nthElement) - 1; 

    // find the nth perfect number 
    nthElement += 9 * outliersCount; 
    return nthElement; 
 

int main() 
 
    cout << findNth(5) << endl; 
    return 0; 
 

最终,我最终写出了算术级数+蛮力的组合,如下所示

#include <bits/stdc++.h>
using namespace std;
#define ll unsigned long long


int main() 
    int n;
    cin >> n;

    int count = 0;
    ll i = 19;
    for (; ; i += 9) 
        int curr = i;
        int localSum = 0;

        while (curr) 
            localSum += curr%10;
            curr /= 10;
        

        if (localSum == 10) 
            count += 1;
        

        if (count == n) 
            break;
         
    
    cout << i << endl;
    return 0;


我想知道,是否没有不需要我计算总和的恒定时间或更好的算法,但我的算法总是以我的数字总和为 10 的方式跳跃?

【问题讨论】:

什么是“AP”?与流行的看法相反,并不是每个人都知道这些缩写的含义。 算术级数。我会编辑。 【参考方案1】:

这是一个可以翻译成 C++ 的 Python 解决方案。

cached_count_ds_l = 
def count_digit_sum_length (s, l):
    k = (s, l)
    if k not in cached_count_ds_l:
        if l < 2:
            if s == 0:
                return 1
            elif l == 1 and s < 10:
                return 1
            else:
                return 0
        else:
            ans = 0
            for i in range(min(10, s+1)):
                ans += count_digit_sum_length(s-i, l-1)
            cached_count_ds_l[k] = ans
    return cached_count_ds_l[k]

def nth_of_sum (s, n):
    l = 0
    while count_digit_sum_length(s, l) < n:
        l += 1
    digits = []

    while 0 < l:
        for i in range(10):
            if count_digit_sum_length(s-i, l-1) < n:
                n -= count_digit_sum_length(s-i, l-1)
            else:
                digits.append(str(i))
                s -= i
                l -= 1
                break
    return int("".join(digits))

print(nth_of_sum(10, 1000))

这个想法是使用动态规划来找出给定最大长度和给定数字总和的数字有多少。然后用它在找到正确数字的过程中划掉整个数字块。

主要逻辑是这样的:

0 numbers of length 0 sum to 10
  - need longer
0 numbers of length 1 sum to 10
  - need longer
9 numbers of length 2 sum to 10
  - need longer
63 numbers of length 3 sum to 10
  - need longer
282 numbers of length 4 sum to 10
  - need longer
996 numbers of length 5 sum to 10
  - need longer
2997 numbers of length 6 sum to 10
  - answer has length 6

Looking for 1000th number of length 6 that sums to 10
  - 996 with a leading 0 sum to 10
    - Need the 4th past 99999
  - 715 with a leading 1 sum to 10
    - Have a leading 1
Looking for 4th number of length 5 that sums to 9
  - 495 with a leading 0 sum to 9
    - Have a leading 10
Looking for 4th number of length 4 that sums to 9
  - 220 with a leading 0 sum to 9
    - Have a leading 100
Looking for 4th number of length 3 that sums to 9
  - 55 with a leading 0 sum to 9
    - Have a leading 1000
Looking for 4th number of length 2 that sums to 9
  - 1 with a leading 0 sum to 9
    - Need the 3rd past 9
  - 1 with a leading 1 sum to 9
    - Need the 2nd past 19
  - 1 with a leading 2 sum to 9
    - Need the 1st past 29
  - 1 with a leading 3 sum to 9
    - Have a leading 10003

寻找总和为 6 的第一个长度为 1 的数字 - 0 前导 0 总和为 6 - 需要过去的 0 - 0 前导 1 总和为 6 - 需要过去 1 - 0 前导 2 总和为 6 - 需要过去2 - 0 前导 3 总和为 6 - 需要过去 3 点 - 0 前导 4 总和为 6 - 需要过去 4 点 - 0 前导 5 总和为 6 - 需要 1 过去 5 - 1 的前导 6 总和为 6 - 有一个领先的100036

它在几分之一秒内完成。

顺便说一下,百万分之一是 20111220000010,十亿分是 10111000000002000000010000002100,万亿分之一是 1000000010000010000010000000000000100000000000000100000000000000000000000

【讨论】:

感谢您的帮助。我无法想象这是一个 DP 问题。

以上是关于919B |第n个数字总和为10 |代码部队的主要内容,如果未能解决你的问题,请参考以下文章

特种部队

PID204特种部队

特种部队(codevs 1427)

RONOJ——PID204 / 特种部队 ☆

nyoj 115 城市平乱

反恐精英(尺取算法)