2015 ACM/ICPC合肥网赛&HDU5491 The Next

来源:互联网 发布:社交软件市场分析 编辑:程序博客网 时间:2024/06/08 19:35

传送门

题意:给出一个数字n,其二进制表示中1的个数在a~b之间,求出个数在a~b之间的比n大的最小的数。

 思路:首先用一个数组存储n的二进制数,从低到高枚举0出现的位置,若把该位置为1,该位之前的全部置0后,若所有1的个数仍然比b大,则向后枚举下一个为0的位置,直到最高位。

 若1的总数大于a小于b,则直接把该位置为1,之前为0,这个数就是最小的数。

 若总数小于a,则从最低位开始往上设置1,由此保证这个数是满足要求的最小的数。

(语文实在不好,没看懂的结合代码看吧)

#include <cstdio>#include <iostream>#include <cstring>#include <cmath>using namespace std;const int maxn = 55;int T,a,b,num[maxn],sum[maxn],cases = 0;long long n,t;int main(){    scanf("%d",&T);    while(T--){        memset(num,0,sizeof(num));        memset(sum,0,sizeof(sum));        scanf("%lld%d%d",&n,&a,&b);        t=n;        int all = 0,pos = 0;        while(t){            if(t&1) all++,num[pos]=1;            t>>=1;pos++;        }        sum[pos-1]=num[pos-1];        for(int i=pos-2;i>=0;i--)            sum[i]+=sum[i+1]+num[i];//        for(int i=pos-1;i>=0;i--)//            cout<<num[i]<<endl;        for(int i=0;i<=pos;i++){            if(!num[i]){                int tempall = sum[i]+1;//                cout<<tempall<<" "<<b<<endl;//                cout<<"--------------"<<endl;                if(tempall>b) continue;                long long ans = 0;                int post = 0;                while(tempall<a){                    ans += pow(2,post);                    post++;                    tempall++;                }//                cout<<ans<<endl;                ans+=pow(2,i);//                cout<<ans<<endl;                for(int j=i+1;j<pos;j++)                    ans += num[j]*pow(2,j);                printf("Case #%d: %lld\n",++cases,ans);                break;            }        }    }    return 0;}


0 0
原创粉丝点击