zoukankan      html  css  js  c++  java
  • number 解题报告

    number

    题目描述

    给定整数 (m,k),求出正整数 (n) 使得 (n+1,n+2,…,2n) 中恰好有 (m) 个数在二进制下恰好有 (k)(1)。 有多组数据。

    输入数据

    第一行一个整数 (t) 表示数据组数。接下来 (t) 行每行两个整数 (m),(k)

    输出数据

    每组数据输出一行两个整数,第一个数表示 (long long) 范围内任意一个满足条件的 (n),第二个数表示满足条件的 (n) 的个数(无穷多用(-1)表示)。 保证 (10^{18}) 以内存在满足条件的 (n)
    如果每组数据第一个数全部正确,得 (4) 分。
    如果每组数据第二个数全部正确,得 (6) 分。

    数据范围

    对于 (10\%) 的数据, (k=2)
    对于 (20\%) 的数据, (k<=3)
    对于另外 (50\%) 的数据, 保证满足条件的 (n) 均在 (10^{18}) 以内。
    对于 (100\%) 的数据, (t<=2000), $0<=m<=10^{18}, (1<=k<=64)


    打表吧。

    然后发现(k)一定时,(m)(n)增大在整数域上连续增大。

    进一步发现,其实(m)变化时的(n)是二进制下(k-1)(1)从小到大排序而成的

    于是可以预处理组合数求一下啦

    要特判(m=0)


    Code:

    #include <cstdio>
    #define ll long long
    ll C[70][70];
    void init()
    {
        C[0][0]=1;
        for(int i=1;i<=67;i++)
        {
            C[i][0]=1;
            for(int j=1;j<=i;j++)
                C[i][j]=C[i-1][j-1]+C[i-1][j];
        }
    }
    int t;
    ll cal(int k,ll m)
    {
        if(m==-1) return 0;
        ll ans=0;
        while(k)
        {
            int pos=k;
            while(C[pos][k]<=m) ++pos;
            --pos;
            ans|=1ll<<pos;
            m-=C[pos][k];
            k--;
        }
        return ans;
    }
    int main()
    {
        init();
        scanf("%d",&t);
        while(t--)
        {
            ll m;int k;
            scanf("%lld%d",&m,&k);
            --k;
            if(!k)
                printf("1 -1
    ");
            else
            {
                ll r=cal(k,m),l=cal(k,m-1);
                printf("%lld %lld
    ",l+1ll,r-l);
            }
        }
        return 0;
    }
    

    2018.10.13

  • 相关阅读:
    git
    ComfortColor.xcs
    使用Jackson时转换JSON时,日期格式设置
    json和jsonp
    powerdesigner 将表中name列值复制到comment列 (保留原有comment)
    下滑线驼峰互转
    Tomcat
    git stash
    gitignore
    例题:大图轮播
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9784250.html
Copyright © 2011-2022 走看看