標籤:構造 hdu 比賽
【連結】click here~~
【題意】:
給你一個D(0≤D<231),保證D的二進位中1的數量在s1和s2之間
然後讓你求一個最小的數,使得這個數的位元量大於等於s1,小於等於s2,且大於 d
【思路】雖然是比賽時候的一道水題,但是開始看到的時候並沒有想到好的思路,最後還是學弟強行過掉,今天突然想到了可以用lowbit來求
首先看到D的範圍是很大的,那麼如何 構造呢?
這裡舉個例子:比如11,二進位表示(1011),取11+1=12,二進位表示(1100)s1=2,那麼我們要做的就是考慮構造數的範圍,如果當前數的s1 小於左區間的值,我們要做的就是從最後一個0出現的位置添加1,也就是從右至左,我們發現對12取按位反後得到(0011),取一次lowbit得到從右往左第一個1的位置是1,那麼我們就把12+1=13(1101),相當於12的十進位加一,也等於12的二進位多添了一個1,這樣是構造小於左區間的,那麼如果大於左區間,又要滿足條件,即取大於D的最小值,不難發現,只要加上lowbit(d)即可
代碼:
/* * Problem: HDU No.5491* Running time: 499MS * Complier: G++ * Author: javaherongwei * Create Time: 8:47 2015/9/28 星期一*/ #include <bits/stdc++.h>using namespace std;typedef long long LL;inline LL read(){ int c=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} return c*f;}LL bitwei(LL x){ LL s=0; while(x){ if(x%2) s++; x/=2; } return s;}LL bitwei2(LL x){ x = (x&0x55555555) + ((x>>1) & 0x55555555); x = (x&0x33333333) + ((x>>2) & 0x33333333); x = (x&0x0F0F0F0F) + ((x>>4) & 0x0F0F0F0F); x = (x&0x00FF00FF) + ((x>>8) & 0x00FF00FF); x = (x&0x0000FFFF) + ((x>>16) & 0x0000FFFF); return x;}LL lowbit(LL x){ return x&(-x);}int main(){ int t,tot=1;t=read(); while(t--){ LL d,s1,s2; d=read();s1=read();s2=read();d++; LL len=bitwei2(d); while(!(len>=s1&&len<=s2)){ if(len<s1) d+=lowbit(~d); else d+=lowbit(d); len=bitwei2(d); } printf("Case #%d: ",tot++); printf("%lld\n",d); } return 0;}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
HDU 5491 The Next 構造(2015 ACM/ICPC Asia Regional Hefei Online)