UVALive 7279 Sheldon Numbers(位运算、暴力、想法)

16 篇文章 0 订阅
14 篇文章 0 订阅

题目链接:

http://7xjob4.com1.z0.glb.clouddn.com/78c8eef4017b53d6dc5ecf5e0bbb6486

题目大意:

在自然数中,存在这么一些数,他们的二进制能够以ABABAB……或者ABAB……A来表示。其中A代表全部由连续的1组成的字符串,B代表全部由连续的0组成的字符串。比如73,二进制表示为1001001。现在给出区间[l,r],问在这个区间里面,有多少个符合条件的数。

范围:0~2^63。

思路:

如果以二进制来看的话,其实我们可以发现这样的数不会太多。所以我们考虑暴力。

因为我们知道了左右区间,所以我们知道了我们需要的数以二进制表示的时候长度len不会超过区间的限制。所以我们可以在len上面枚举1和0的情况,枚举出来的数保证是符合条件的但可能有一部分是超出区间范围的,然后利用位运算直接把他算出来放到set里面,最后判断一下set里面有多少个符合条件的数即可。

代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<set>
#define ll long long
using namespace std;
int main()
{
    int i,j,k,t1,t2,ans;
    ll x,y,a,b;
    set<ll>st;
    while(~(scanf("%lld%lld",&x,&y)))
    {
        ans=0;
        st.clear();
        t1=t2=0;
      a=x;
      b=y;
      while(a){
        t1++;
        a=a/2;
      }
      while(b){
        t2++;
        b=b/2;
      }
      ll sum=0;
  //    printf("%d %d\n",t1,t2);
      for(int len=t1;len<=t2;len++)
      {
          for(i=1;i<=len;i++)
          {
              for(j=0;j<=len-i;j++)
              {
                  if(len%(i+j)==0){
                    int x=len/(i+j);
                    sum=0;
                    while(x){
                            for(k=1;k<=i;k++)
                        sum+=1<<(x*(i+j)-k);
                        x--;
                    }
                    st.insert(sum);
                  }
                  if((len-i)%(i+j)==0){
                    int x=(len-i)/(i+j);
                    sum=0;
                    while(x){
                            for(k=1;k<=i;k++)
                        sum+=1<<(x*(i+j)-k+i);
                        x--;
                    }
                    for(k=1;k<=i;k++)
                    sum+=1<<(k-1);
                    st.insert(sum);
                  }
              }
          }
      }
      set<ll>::iterator it;
      for(it=st.begin();it!=st.end();it++)
      {

          if(*it>=x&&*it<=y){ans++;}
      }
      if(x==0)ans++;
      printf("%d\n",ans);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值