求满足C(n,k) = x的数目,x高达10^15
直接枚举是不可能的,因为x高达10^15,一定有C(x, 1) = x;
那么为了降低枚举的数目,可以从k考虑。
当k = 1, k = 2, k = 3的时候如果有满足的可以把n直接算出来。
如果没有满足的,当k从4开始的时候,那么至少是n * (n - 1) * (n - 2) * (n - 3) / 16 = x了。
那么n只要枚举到10000即可。
注意答案判重,可能k = n / 2时候答案有重复。
也可以再加入答案的时候判重,k != n - k 即可。
当然要注意一下直接枚举k = 1, k = 2和k = 3的时候有没有重复答案。。
为了简单直接先把答案加进去然后再判重。
AC代码:
#include <cstdio>
#include <string.h>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAX_NUMBER = 100006;
long long number;
struct Node {
long long n;
long long k;
};
bool cmp(Node a, Node b) {
if (a.n == b.n) {
return a.k < b.k;
}
else {
return a.n < b.n;
}
}
struct Node ans[MAX_NUMBER];
int ans_number;
long long getCom(long long k, long long n) {
long long result = 1;
for (long long i = 1; i <= k; i++) {
result = result * (n - i + 1) / i;
}
return result;
}
void addAns(long long k, long long n) {
ans_number++;
ans[ans_number].k = k;
ans[ans_number].n = n;
ans_number++;
ans[ans_number].k = n - k;
ans[ans_number].n = n;
}
int main() {
int test_case;
scanf("%d", &test_case);
while (test_case--) {
scanf("%lld", &number);
ans_number = 0;
addAns(1, number);
long long n = (long long)sqrt(2 * number + 0.5);
n++;
if (getCom(2, n) == number) {
addAns(2, n);
}
n = (long long)pow(6 * number + 0.5, 1.0 / 3);
n += 2;
if (getCom(3, n) == number) {
addAns(3, n);
}
for (n = 4; n <= 10000; n++) {
for (long long k = 4; k <= n / 2; k++) {
long long temp = getCom(k, n);
if (temp > number) {
break;
}
if (temp == number) {
addAns(k, n);
break;
}
}
}
long long real_ans = 1;
sort(ans + 1, ans + 1 + ans_number, cmp);
for (int i = 2; i <= ans_number; i++) {
if (ans[i].k != ans[i - 1].k || ans[i].n != ans[i - 1].n) {
real_ans++;
}
}
printf("%lld\n", real_ans);
for (int i = 1; i <= ans_number; i++) {
if (i == 1) {
printf("(%lld,%lld)", ans[i].n, ans[i].k);
}
else if (ans[i].k != ans[i - 1].k || ans[i].n != ans[i - 1].n) {
printf(" (%lld,%lld)", ans[i].n, ans[i].k);
}
}
printf("\n");
}
return 0;
}