【HDU】5491 The Next(2015 ACM/ICPC Asia Regional Hefei Online)

The Next


題目鏈接


題目大意

    規定一種數叫做WYH數,其二進制中1的個數在s1,s2之間,現在給你一個WYH數,要你求比他大的WYH數中最小的一個(就是下一個WYH數)


題解

構造

    其實這一題挺有意思的…
    考慮比D大1的數D+1,先算出D+1中1的個數L,然後分情況討論:

  • 如果L大於S2
        因爲我們現在要減少1的個數,而且我們現在只能加,所以考慮二進制中的最後一個1,只有讓這一位向前進位,我們才能減少1的個數,所以對於這種情況,我們先找出最後一個1所在的位置,然後把該位的1向前進位。

  • 如果L小於S1
        這個好說,我們從二進制的最右邊向左邊掃,把遇到的0全部變成1,知道滿足條件爲止。


代碼

#include <iostream>
#include <cstring>
#include <cstdio>
#define LL long long

using namespace std;

int T,s1,s2;
LL d;

int num(LL a)
{
    int ans=0;
    for (int i=0;i<32;i++) if ((1<<i)&a) ans++;
    return ans;
}

int main()
{
    int Case=1;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%I64d%d%d",&d,&s1,&s2);
        d++;
        int l=num(d);
        printf("Case #%d: ",Case++);
        if (l>=s1 && l<=s2)
        {
            printf("%I64d\n",d);
            continue ;
        }
        while (1)
        {
            if (l<s1)
            {
                for (int i=0;i<32;i++)
                    if (((1<<i)&d)==0)
                {
                    d=d|(1<<i);
                    l++;
                    if (l==s1) break;
                }
                printf("%I64d\n",d);
                break;
            }
            if (l>s2)
            {
                for (int i=0;i<32;i++) if ((1<<i)&d)
                {
                    d+=(1<<i);
                    break;
                }
                l=num(d);
                if (l>=s1 && l<=s2)
                {
                    printf("%I64d\n",d);
                    break;
                }
            }
        }
    }
    return 0;
}
發佈了215 篇原創文章 · 獲贊 4 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章