absi2011's Blog & Daily Life.

全新的开始       我要省选翻盘       I wanna AK in 高考\化学       自此,生无可恋
100729 G 解题报告
100729 F 解题报告

100729 A 解题报告

absi2011 posted @ Dec 02, 2015 11:31:11 PM in 刷题记录 with tags 搜索 CF Gym 数学题 , 500 阅读

链接链接http://codeforces.com/gym/100729/attachments/download/3754/20112012-northwestern-european-regional-contest-nwerc-2011-en.pdf

题意:给你n

求出所有的C(m,k)=n

这一题..n<=10^15

所以做法就比较有趣了

首先就是可以得到一个规律

C的增长相当快,C(100,10)=17,310,309,456,440 > 1e15

那么我们可以考虑

对于k=1到10的时候,分别枚举,二分,求出一个对应的k

如果对于同一个n而言(n>100),k的增大(<50的情况下)只会让值变得更大

那么我们只要知道k在11~n-11之间几乎(好像也是完全)无解的

那么只要暴力枚举以后二分出m即可,注意去重

代码如下:

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<string>
#include<math.h>
#include<time.h>
#include<vector>
#include<bitset>
#include<memory>
#include<utility>
#include<fstream>
#include<stdio.h>
#include<sstream>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct answer
{
    long long x;
    long long y;
    friend bool operator < (const answer &a,const answer &b)
    {
        if (a.y!=b.y) return a.y<b.y;
        return a.x<b.x;
    }
    friend bool operator == (const answer &a,const answer &b)
    {
        return !((a<b)||(b<a));
    }
    void output()
    {
        cout<<"("<<y<<","<<x<<") ";
    }
};
answer ans[10005];
long long c[105][105];
long double check(long long x,int y)
{
    int i;
    long double t=0;
    for (i=1;i<=y;i++)
    {
        t+=log10((long double)(x+1-i));
        t-=log10((long double)i);
    }
    return t;
}
long long cc(long long x,int y)
{
    int i;
    long long t=1;
    for (i=1;i<=y;i++)
    {
        t*=(x+1-i);
        t/=i;
    }
    return t;
}
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    int t;
    scanf("%d",&t);
    int zu;
    int i,j;
    c[0][0]=1;
    for (i=1;i<=100;i++)
    {
        c[i][0]=1;
        for (j=1;j<=100;j++)
        {
            c[i][j]=c[i-1][j-1]+c[i-1][j];
            if (c[i][j]>10000000000000000ll) c[i][j]=10000000000000000ll;
        }
    }
    for (zu=0;zu<t;zu++)
    {
        long long n;
        cin>>n;
        int i,j;
        int sum=0;
        for (i=0;i<=100;i++)
        {
            for (j=0;j<=100;j++)
            {
                if (c[i][j]==n)
                {
                    ans[sum].x=j;
                    ans[sum].y=i;
                    sum++;
                }
            }
        }
        for (i=1;i<=10;i++)
        {
            long long l=i,r=n;
            for (;l<=r;)
            {
                long long mid=(l+r)/2;
                if (check(mid,i)<=log10((long double)n))
                {
                    l=mid+1;
                }
                else
                {
                    r=mid-1;
                }
            }
            long long t=cc(r,i);
            if (t==n)
            {
                ans[sum].x=i;
                ans[sum].y=r;
                sum++;
                ans[sum].x=r-i;
                ans[sum].y=r;
                sum++;
            }
            t=cc(l,i);
            if (t==n)
            {
                ans[sum].x=i;
                ans[sum].y=l;
                sum++;
                ans[sum].x=l-i;
                ans[sum].y=l;
                sum++;
            }
        }
        sort(ans,ans+sum);
        sum=unique(ans,ans+sum)-ans;
        cout<<sum<<'\n';
        for (i=0;i<sum;i++)
        {
            ans[i].output();
        }
        cout<<'\n';
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter