数字为 sum s 的 k 位整数数组
Posted
技术标签:
【中文标题】数字为 sum s 的 k 位整数数组【英文标题】:Array of k-digit integers with digits of sum s 【发布时间】:2020-12-06 08:58:16 【问题描述】:我的任务是编写一个程序,找出其位数等于 s 的 k 位数数组的最大和最小元素。例如, 输入:1 3 输出:101 101 输入:2 3 输出:200 101
我在这个例子中得到了正确的输出,但是当我输入“10 10”时程序不工作并且它给出了运行时错误。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
int main()
int s, k;
cin >> s >> k;
int count = 0;
int fsum = 0, fcnt = 0, scnt = 0;
vector <int> vec;
int i = pow(10, k - 1);
while (i < pow(10, k))
int ssum = 0, num = i;
while (num)
ssum += num % 10;
num /= 10;
if (ssum == s)
vec.push_back(i);
scnt++;
i++;
cout << *max_element(vec.begin(), vec.end()) << " " << *min_element(vec.begin(), vec.end()) << endl;
return 0;
【问题讨论】:
pow(10, 10)
超出了int
的典型限制。你应该使用更大的整数类型,比如long long
或者使用字符串来存储东西。
你能解释一下测试用例input: 1 3 output: 101 101
吗?数字总和等于 2...我可能会漏掉一些东西
在这么大的数字中进行暴力破解太低效了。您将不得不编写更高效的代码。仔细看小例子。想想什么类型的整数大,什么类型的小。
@MikeCAT 是的,我想通了,但现在它显示时间错误,所以我认为我应该为这项任务使用不同的方法
@Damien 在这种情况下,该数组仅包含一个元素 101。因此,它同时是最大元素和最小元素
【参考方案1】:
像往常一样,此类问题不应使用蛮力来回答。这将导致大量的时间和内存消耗。
这样的问题,总是好的算法会赢。
所以,让我们想想。一个要求是找到一个其指定位数之和最大的值。这样一个数字的最大可能总和是多少。这很容易。所有数字都是 9。因此 4 位值的最大可能总和将是 9999 -> 36。我们观察到在数字开头有尽可能多的“9”会很聪明,然后将其余部分放入下一位数字。
示例:5 位数字,总和为 25。
这里我们将从 9 开始,因为它适合,其余为 16。我们可以添加一个额外的 9,其余为 7。所以 99700 是解决方案。所有这些都可以通过整数模除法一次性计算出来。
25 / 9 = 2(整数除法)。所以,我们需要两个。 '9' 在数字的开头。模除法
25 % 9 = 7。这是余数和缺失的数字。
其余请求的位数将用零填充。
对于最小数,我们只需要将最大数取反即可。很简单。
如果最小数量以一开头,那么我们将构建一些简单的特殊处理。
请看下面的代码。
它没有数组或std::vector
。它只是即时打印出数字。不需要额外的存储空间。只是数学
#include <iostream>
// If the smallest number shall have a leading 1
constexpr bool Leading1Required true ;
int main()
// Here we will store our input values
unsigned long sumOfDigits, countOfDigits;
// Do some plausibility checks
if (!(std::cin >> sumOfDigits >> countOfDigits)) std::cerr << "\nError while reading input\n";
else if (countOfDigits < 1) std::cerr << "\nError: Count of digits must be greater than 0\n";
else if (sumOfDigits > countOfDigits * 9) std::cerr << "\nError Sum of digits can never be reached\n";
else
// Ok, now we have some valid values
// Output maximum value
for (unsigned long i; i < countOfDigits; ++i)
if (i < (sumOfDigits / 9UL)) std::cout << '9';
if (i == (sumOfDigits / 9UL)) std::cout << (sumOfDigits % 9UL);
if (i > (sumOfDigits / 9UL)) std::cout << '0';
std::cout << ' ';
// This will be compiled conditionally
// In case that we want a leading 1 for the minimum value
if constexpr (Leading1Required)
// So, the reuqested digit sum will be one less, because we want to have a leading 1
if (sumOfDigits > 0)
if (sumOfDigits > 9)
--sumOfDigits;
--countOfDigits;
// Output the leading one in any case
std::cout << '1';
else std::cerr << "\nError: Sume of 0 cannot be reached with a leading 1\n";
// Now print the minimum number (is the reverse from the maximum number)
for (unsigned long i; i < countOfDigits; ++i)
if (i > (countOfDigits -sumOfDigits / 9UL)-1) std::cout << '9';
if (i == (countOfDigits -sumOfDigits / 9UL)-1) std::cout << (sumOfDigits % 9UL);
if (i < (countOfDigits -sumOfDigits / 9UL)-1) std::cout << '0';
std::cout << '\n';
return 0;
【讨论】:
【参考方案2】:一个更快的解决方案是处理一个数字数组,并以贪婪的方式分配值。
我们只需要注意,较低值的MSB不能等于0。
input: 10 10
output 9100000000 1000000009
代码:
注意:此代码假定输入是连贯的,即sum <= 9*k
。如果没有,可以添加一个简单的测试。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
//using namespace std;
// Print an array, MSB first = last element
void print (const std::vector<int> vec)
for (int i = vec.size()-1; i >= 0; --i)
std::cout << vec[i];
int main()
int sum, k;
std::cin >> sum >> k;
std::vector<int> vmax(k), vmin(k);
int s = sum;
int index = k-1;
while (index >= 0 && s > 0)
int digit = std::min(s, 9);
vmax[index--] = digit;
s-= digit;
s = sum;
index = 0;
while (index < k && s > 0)
int digit = std::min(s, 9);
vmin[index++] = digit;
s-= digit;
if (vmin[k-1] == 0)
vmin[k-1] = 1;
vmin[index-1]--;
print (vmax);
std::cout << " ";
print (vmin);
std::cout << "\n";
return 0;
【讨论】:
以上是关于数字为 sum s 的 k 位整数数组的主要内容,如果未能解决你的问题,请参考以下文章
c_cpp [阵] 3sum最近。给定n个整数的数组S,在S中找到三个整数,使得总和最接近给定数字target。 Retur