给我a,b和c。 a-b是范围,c是所需数字 所需的输出是该范围内的数字总数为c的数字数量。 这些是条件: (1≤A≤B <1015,1≤C≤135) 我当前的代码利用
while (num != 0){
sum = sum + num % 10;
num = num / 10;
}
但是要获得完整的正确答案太慢了;
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
long long int a, b, c;
long long int sum = 0;
long long int num;
long long int finalone;
long long int counter = 0;
string arr[b];
cin >> a >> b >> c;
for (long long int x=a; x<b; x++){
num = x;
while (num != 0){
sum = sum + num % 10;
num = num / 10;
}
if (sum == c && counter == 0){
finalone = x;
}
if (sum == c){
counter++;
}
sum = 0;
}
cout << counter << endl;
cout << finalone;
}
答案 0 :(得分:0)
考虑到这一点
c > 9 + 9 + 9 = 27
,则为counter = 0
。counter(a, b) = counter(1, b) - counter(1, a)
。我们可能会得出结论,您只有1014*27 = 27378
个可能的输入。这意味着您可以预先计算27378个值中的每个值,将它们存储在数组中,并将函数简化为参数范围检查,2个表查找和1个减法。这应该是最快的解决方案:)
答案 1 :(得分:0)
首先,请注意,您的问题陈述有些混乱。如果您考虑的数字最大为1015
,那么您可以获得的最大数字总和是999
,并且是27
。因此,我们已经知道有多少个数字的总和为27 < c <= 135
;)。
接下来,您的算法做了很多不必要的计算。对于该范围内的每个数字,大多数情况下只有一位数字发生变化时,您可以使用模来重新计算每个位数。如果将数字存储在数组中,“手动”增加数字并添加数组元素,则可以改进代码。虽然,这不会提高复杂性。
尝试从另一个角度看问题。基本上,您必须找到四个数字的组合,以使w+x+y+z = c
和这些数字的“串联”落入[a,b]
范围内。例如,当c==4
时,只有很少的组合:
1111, 211, 121, 112, 31, 22, 13
一旦有了这些数字,便可以很容易地计算出其中有多少属于给定范围。
出于乐趣,我决定看看是否可以在编译时实施蛮力策略。我们可以这样计算出数字的总和:
template <int x>
using number = std::integral_constant<int,x>;
template <int x>
struct sum_of_digits : number< sum_of_digits<x/10>::value + (x%10)> {};
template <>
struct sum_of_digits<0> : number<0> {};
我使用助手检查两个整数是否相等
template <int x,int y>
struct equals : std::false_type {};
template <int x>
struct equals<x,x> : std::true_type {};
将两者放在一起,我们可以检查一个数字是否具有给定的数字总和:
template <int x,int c>
struct is_sum_of_digits : equals<c,sum_of_digits<x>::value> {};
现在我们在[0,a]
中用正确的数字总和来计数数字:
template <int a,int c>
struct count : number<is_sum_of_digits<a,c>::value + count<a-1,c>::value> {};
template <int c>
struct count<0,c> : number<0> {};
在此示例中,我仅使用最多三位数的数字。限制是我正在使用的std::index_sequence
中的模板递归。您可能需要加快-ftemplate-depth
的编制,才能获得更多的数字,而且我不得不展开其中一个尺寸,以免达到我的编译器限制。使用编译时结果,我填写了一个查找表以在运行时获取结果:
const int max_b = 100; // max sum of digits is 18 for 99
template <std::size_t ... is>
int get_number_of_correct_sum_impl(int a,int b,int c,std::index_sequence<is...>){
static constexpr int table[] = { count<is,0>::value...,
count<is,1>::value... , count<is,2>::value... ,
count<is,3>::value... , count<is,4>::value... ,
count<is,5>::value... , count<is,6>::value...,
count<is,7>::value... , count<is,8>::value... ,
count<is,9>::value... , count<is,10>::value... ,
count<is,11>::value... , count<is,12>::value... ,
count<is,13>::value... , count<is,14>::value... ,
count<is,15>::value... , count<is,16>::value... ,
count<is,17>::value... , count<is,18>::value...
};
auto index = [max_b = max_b](int a,int c){ return c*max_b + a; };
return table[index(b,c)] - table[index(a,c)];
}
int get_number_of_correct_sum(int a,int b,int c){
return get_number_of_correct_sum_impl(a,b,c,std::make_index_sequence<max_b>{});
}
然后
int main() {
for (int i=1;i<33;++i){
std::cout << i << " " << get_number_of_correct_sum(0,i,5) << "\n";
}
}
打印:
1 0
2 0
3 0
4 0
5 1
6 1
7 1
8 1
9 1
10 1
11 1
12 1
13 1
14 2
15 2
...etc...
请注意,这仍然只是蛮力检查所有数字并计算满足条件的数字,但这是在编译时完成的。在运行时剩下的就是在查找表中查找两个条目并取它们的差值,即O(1)
。
PS:有关查找表的帮助,分为https://stackoverflow.com/a/55543931/4117728和https://stackoverflow.com/a/55543946/4117728