【枚举】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 }
View Code

 

posted @ 2017-07-28 22:30  shulin15  阅读(164)  评论(0编辑  收藏  举报