【枚举】Southwestern Europe Regional Contest H - Sheldon Numbers
https://vjudge.net/contest/174235#problem/H
【题意】
- 求[x,y]之间有多少个Sheldon Number
- Sheldon Number是二进制满足以下条件的数:
- 可以写成ABABAB . . . ABA或ABABAB . . . AB,其中,A是连续的n个1,B是连续的m个0
- 这个二进制数可以没有0但不能没有1
【思路】
- 对于确定的n,m,和二进制数的长度len,二进制数唯一确定的,所以按n,m,len枚举的话复杂度为64^3
- 我们可以预处理所有的Sheldon Number,保存在数组中,排序
- 可能有重复,所以要去重
- 对所求的[x,y],在数组中二分查找x和y,x为lower_bound,y为upper_bound-1
【Accepted】
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 #include<cmath> 7 8 using namespace std; 9 typedef unsigned long long ull; 10 typedef long long ll; 11 ll x,y; 12 ll two[63]; 13 ll ans[262150]; 14 void init() 15 { 16 two[0]=1ll; 17 for(int i=1;i<=63;i++) 18 { 19 two[i]=two[i-1]*2; 20 } 21 } 22 ll calc(int n,int m,int len) 23 { 24 int digit[64]; 25 int cntn=0,cntm=0; 26 for(int i=0;i<len;i++) 27 { 28 if(cntn<n) 29 { 30 digit[i]=1; 31 cntn++; 32 if(cntn==n) 33 { 34 cntm=0; 35 } 36 } 37 else 38 { 39 digit[i]=0; 40 cntm++; 41 if(cntm==m) 42 { 43 cntn=0; 44 } 45 } 46 } 47 ll res=0ll; 48 for(int i=0;i<len;i++) 49 { 50 res+=1ll*digit[i]*two[len-1-i]; 51 } 52 return res; 53 54 } 55 int main() 56 { 57 init(); 58 int cnt=0; 59 for(int i=1;i<=63;i++) 60 { 61 for(int j=0;j<=63;j++) 62 { 63 for(int k=1;k<=63;k++) 64 { 65 if((j==0&&k%i==0&&k/i>=1)||(j!=0&&k%(i+j)==0&&k/(i+j)>=1)||(j!=0&&(k+j)%(i+j)==0&&(k+j)/(i+j)>=2)) 66 { 67 ans[cnt++]=calc(i,j,k); 68 } 69 } 70 } 71 } 72 sort(ans,ans+cnt); 73 cnt=unique(ans,ans+cnt)-ans; 74 while(~scanf("%lld%lld",&x,&y)) 75 { 76 int p=lower_bound(ans,ans+cnt,x)-ans; 77 int q=upper_bound(ans,ans+cnt,y)-ans-1; 78 cout<<q-p+1<<endl; 79 } 80 return 0; 81 }