#include <iostream>
#include <algorithm>
#include <cstring>
#include <map>
#include <queue>
#include <vector>
#define M(a,b) make_pair(a,b)
#define pll pair<long long ,long long>
using namespace std;
typedef long long ll;
const int N=1e3+20;
ll m;
priority_queue< pll,vector<pll >,greater<pll > > q;
ll C(ll n,ll k)
{
ll x=1;
for(int i=1;i<=k;i++)
{
if ((x/ i)>(m / (n - i + 1)))//如果发现算到第i步时结果已经超过m了,说明n肯定不是解,返回一个m+1
return m + 1;
x*=(n-i+1);
x/=i;
}
return x;
}
void solve()
{
for(int k=1;C(2*k,k)<=m;k++)//c(n,k) n从2*k开始枚举
{
ll l=2*k;
ll r=m;
while(l<=r)
{
ll n=(l+r)/2;
ll t=C(n,k);
if(t<=m)
{
if(t==m)
{
q.push(M(n,k));
if(n==2*k)//一样
break;
q.push(M(n,n-k));
break;
}
l=n+1;
}
else
{
r=n-1;
}
}
}
}
int main()
{
//c(n,k)=m m<=1e15 给求m 求 n,k
//选对枚举对象,枚举n的话 (m,1)=1 n的范围会很大 若枚举k呢?
//c(n,k)=c(n,n-k) 因为是枚举k,固定n 只要前面一个较小的k即可,该n的第二个k'=(n-k)就能得出
//k<=n-k n>=2k 所以固定k后,在2k~m内二分出n即可
int t;
cin>>t;
while(t--)
{
cin>>m;
solve();
ll len=q.size();
cout<<len<<endl;
if(len)
for(int i=0;i<len;i++)
{
cout<<'('<<q.top().first<<","<<q.top().second<<")";
if(i==len-1)
cout<<endl;
else
cout<<' ';
q.pop();
}
}
return 0;
}
uva 1649 Binomial coefficients 枚举+二分
最新推荐文章于 2019-08-12 11:23:00 发布