我们给了3个变量d
,a
和b
。
d
指定最大位数。
a
和b
分别指定最小位数和最大位数。
我们必须找出可以制造多少个数字,每个数字的数字都以不降序的顺序进行排列,最大位数为d,a和b之间的每个数字都包含在内。
Ex-
d = 1
a = 8
b = 9
Answer = 2 (Possible numbers are 8 and 9)
Ex-
d = 2
a = 8
b = 9
Answer = 5 (Possible numbers are 8, 9, 88, 89, and 99)
我曾尝试应用,置换和组合,但是无法找到所有d值的通用答案。
此外,我试图观察每个位数可能出现的模式,但似乎有所不同。
实际的方法是什么?
答案 0 :(得分:0)
您正在寻找具有重复性的组合。我们要做的就是针对每个特定长度(不超过d
)重复生成您的集合的所有组合。
下面,我们在C++
中有一个简单的实现。首先,我们需要适当的include
以及一个用于返回具有重复的组合数(即nChooseK
)的函数:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
int nChooseK(int n, int k) {
int nCk = 1;
for (int i = (n - k + 1), d = 1; d <= k; ++i, ++d) {
nCk *= i;
nCk /= d;
}
return round(nCk);
}
这是生成具有重复的组合的算法:
void combsWithRep(std::vector<int> v, int d) {
int numIter, maxZ, count = 0;
int n = v.size();
int d1 = d - 1, d2 = d - 2;
std::vector<int> z(d, 0);
int numRows = nChooseK(n + d - 1, d);
maxZ = n - 1;
while (count < numRows) {
numIter = n - z[d1];;
for (int i = 0; i < numIter; ++i, ++count, ++z[d1]) {
for (int k = 0; k < d; ++k) {
std::cout << v[z[k]];
}
std::cout << std::endl;
}
for (int i = d2; i >= 0; i--) {
if (z[i] != maxZ) {
++z[i];
for (int k = (i + 1); k < d; ++k)
z[k] = z[k - 1];
break;
}
}
}
}
这是main
函数:
int main() {
std::vector<int> v;
int d, input;
std::cout << "Enter the number of possible digits" << std::endl;
std::cin >> d;
std::cout << "\nEnter the digits" << std::endl;
while (std::cin >> input)
v.push_back(input);
std::sort(v.begin(), v.end());
for (int i = 1; i <= d; ++i)
combsWithRep(v, i);
return 0;
}
因此,输入以下内容:
Enter the number of possible digits
4
Enter the digits
7
8
9
输出为:
7
8
9
77
78
79
88
89
99
777
778
779
788
789
799
888
889
899
999
7777
7778
7779
7788
7789
7799
7888
7889
7899
7999
8888
8889
8899
8999
9999