UVALive 7279 Sheldon Numbers 【位运算】【暴力】

来源:互联网 发布:如何获取股票交易数据 编辑:程序博客网 时间:2024/05/16 10:45

题目:点击打开链接

题意:定义一种谢尔登数,满足其二进制表示为从左到右连续个1,再连续个0或者没有零,然后接着循环或者不循环,若循环,每次都是连续与第一次相同个数的1和相同个数的0,结尾为1或者0,如73的二进制1001001,4的二进制100,9的二进制1001都是谢尔登数。给出一个区间[L,R],求出其区间内谢尔登数的个数。0<=L<=R<=(1<<63)。

分析:由于谢尔登数的循环性质,所有所有的谢尔登数并不多,因此可以暴力预处理出所有的谢尔登数存到数组中,然后查找时二分找到其下标即可。需要注意的是1<<63超出了long long的最大值,要用unsigned long long  储存,并且输入值可能为0,因此也要把0存到数组中。

#pragma comment(linker, "/STACK:1024000000,1024000000")#include <stdio.h>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#include <set>#include <vector>#include <map>#define PR pair<int,int>#define MP make_pair#define fi first#define se second#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define sqr(x) ((x)*(x))#define ll unsigned long longconst ll INF = 1e18;const int inf=0x3f3f3f3f;const int M=100010;const int N=1000;const ll MOD=1000000007;const double eps=1e-8;const double pi=acos(-1.0);using namespace std;ll n,m;vector<ll> vt;void init(){    vt.push_back(0);    int i,j,k;    for(i=1;i<=63;i++)    {        ll t1=((ll)1<<i)-1;        for(j=0;i+j<=63;j++)        {            ll tx=t1<<j;            vt.push_back(tx);            if(j&&(i+j)+i<=63) vt.push_back((tx<<i)+t1);            for(k=2;(i+j)*k<=63&&j;k++)            {                tx=(tx<<(i+j))+(t1<<j);                vt.push_back(tx);                if((i+j)*k+i<=63) vt.push_back((tx<<i)+t1);            }        }    }}int getid(ll x){    int tmp=lower_bound(vt.begin(),vt.end(),x)-vt.begin();    if(vt[tmp]!=x) return tmp-1;    else return tmp;}int main(){    init();    sort(vt.begin(),vt.end());    while(~scanf("%lld%lld",&n,&m))    {        if(n==0) n=1;        if(m==0) m=1;        printf("%d\n",getid(m)-getid(n-1));    }}


0 0
原创粉丝点击