Description
Gunnar is quite an old and forgetful researcher. Right now he is writing a paper on security in social networks and it actually involves some combinatorics. He wrote a program for calculating binomial coefficients to help him check some of his calculations.
A binomial coefficient is a number
,
Gunnar used his program to calculate n
and got a number m as a result. Unfortunately, since he is forgetful, he forgot the numbers n and k he used as input. These two numbers were a result of a long calculation and they are written on one of many papers lying on his desk. Instead of trying to search for the papers, he tried to reconstruct the numbers n, k from the output he got. Can you help him and find all possible candidates?
Input
On the first line a positive integer: the number of test cases, at most 100. After that per test case:
- one line with an integer m (2
m
1015): the output of Gunnar's program.
Output
Per test case:
- one line with an integer: the number of ways of expressing m as a binomial coefficient.
- one line with all pairs (n, k) that satisfy n
= m. Order them in increasing order of n and, in case of a tie, order them in increasing order of k. Format them as in the sample output.
Sample Input
2 2 15
Sample Output
1
(2,1)
4
(6,2) (6,4) (15,1) (15,14)
主要学习别人的代码的STL的使用;
#include <stdio.h>
#include <vector>
#include <string.h>
#include <iostream>
#include <math.h>
#include <map>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PLL;
#define MAX 1000000000000009LL
LL C[1000][1000];
void makeC()
{
memset(C, 0, sizeof (C));
for (int i = 0; i < 1000; i++)
{
C[i][0] = 1;
for (int j = 1; j <= i; j++)
{
C[i][j] = C[i-1][j-1] + C[i-1][j];
C[i][j] = min(C[i][j], MAX);
}
}
}
LL getC(LL a, LL b)
{
LL ret = 1;
for (LL i = 1; i <= b; i++)
{
LL tmp = ret * (a + 1 - i) / i;
if (ret == tmp * i / (a + 1 - i))
{
ret = tmp;
}
else
{
return MAX;
}
}
return ret;
}
vector<PLL> ans;
void gao(LL n)
{
ans.clear();
for (int i = 1; i < 1000; i++)
{
for (int j = 1; j <= i; j++)
{
if (C[i][j] == n)
{
ans.push_back(PLL(i, j));
}
}
}
for (int i = 1; i < 10; i++)
{
LL l = 1;
LL r = n;
while (l <= r)
{
LL m = (l + r) >> 1;
LL t = getC(m, i);
if (t == n)
{
ans.push_back(PLL(m, i));
ans.push_back(PLL(m, m - i));
break;
}
else if (t > n)
{
r = m - 1;
}
else
{
l = m + 1;
}
}
}
sort(ans.begin(), ans.end());
ans.resize(unique(ans.begin(), ans.end()) - ans.begin());
}
int main ()
{
makeC();
int T;
cin >> T;
while (T--)
{
LL n;
cin >> n;
gao(n);
int sz = ans.size();
cout << sz << endl;
for (int i = 0; i < sz; i++)
{
if (i)
{
cout << " ";
}
cout << "(" << ans[i].first << "," << ans[i].second << ")";
}
cout << endl;
}
return 0;
}
本文探讨了一道经典的算法题目,即给定一个二项系数的计算结果m,反求可能的输入值n和k。文章通过预计算一定范围内的二项系数并采用二分查找等方法高效解决此问题。
3260

被折叠的 条评论
为什么被折叠?



