预处理 Gym - 101128H

题目链接:http://codeforces.com/gym/101128

 

 

题目大意:给你一个区间[x,y],找出这个区间有多少个seldom的数字。

seldom的数字定义如下:该数值的二进制数字符合如下条件ABAB...ABAB 或者 ABABA....BA,其中A表示连续的1的个数,B表示连续的0的个数。

 

思路:因为长度只有63,本来以为是数位dp的,想了想直接暴力预处理就好了

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
LL x, y;
vector<LL> ve;

void solve(LL tmp, LL tmp1, LL i, LL j, int len){
    int cnt = 1;
    while (true){
        if (cnt % 2 == 1){
            cnt++;
            if (len + i > 63) break;
            len += i;
            tmp = tmp << i; tmp += tmp1;
            ve.pb(tmp);
        }
        else {
            cnt++;
            if (len + j > 63) break;
            len += j;
            tmp = tmp << j;
            ve.pb(tmp);
        }
        //printf("tmp = %lld\n", tmp);
    }
}

void init(){
    for (int i = 1; i <= 63; i++){///这个是1的东西
        LL tmp1 = 0;
        for (int f = 0; f < i; f++){
            tmp1 |= (1LL << f);
        }
        ve.pb(tmp1);
        for (int j = 1; j <= 63; j++){///这个是0的东西
            if (i + j > 63) break;
            LL tmp = tmp1 << j;
            ve.pb(tmp);
            solve(tmp, tmp1, i, j, i + j);
        }
    }
    sort(ALL(ve));
}

int main(){
    init();
    while (scanf("%lld%lld", &x, &y) == 2){
        int lb = lower_bound(ve.begin(), ve.end(), x) - ve.begin();
        int rb = upper_bound(ve.begin(), ve.end(), y) - ve.begin();
        printf("%d\n", rb - lb);
    }
    return 0;
}
View Code

 

posted @ 2017-04-24 18:31  知る奇迹に  阅读(196)  评论(0编辑  收藏  举报