题意:0 《= low《= high 《= 16 e11。比如low=2.high=3,求的是C【2】【0】,C[2][1],C【2】【2】。。C【3】【3】所有数中的奇数的个数。
题解:感觉就是只看C【i】【】的i就能够决定它的个数。打了个表,发现有重复的规律,从2的整次幂就会从头开始,但是数量会很多。于是再看1,23,4567,89101112131415,的和,发现是2,6,18,54.发现规律了!就是整次幂的就是前面的3倍。而且因为前面一半的都一样,那么其实是1+2的分布的。所以给出一个r,1~r的很好算。就是先搞出前面整的,然后最后一段:看是否长度大于一半,大于的话,先算出前面一半,然后加2倍的后面一半往前平移一段。log级别的就好了。长度小于一半的话直接就跑到前面的。这样就搞定了。0的情况特殊想下
重点:感觉出只由i应该就能决定,其次打表看发现有2幂次的小关系,再打和的表再发现出1+2的分布。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(ull i = a;i < b;i++)
#define REP_D(i, a, b) for(ull i = a;i <= b;i++)
typedef long long ll;
typedef unsigned long long ull;//llu
using namespace std;
const ull maxn = 40;
const double EPS = 1e-10;
ull d[maxn];
void getD()//整段的,i代表2的幂次
{
d[0]=2;
d[1]=6;
d[2]=18;
for(ull i = 3;i <= maxn-1;i++)
{
d[i]=d[i-1]*3;
//printf("%d\n", d[i]);
}
}
ull gao(ull s, ull n)//从2的s幂搞起,长度有n。其实就是分两种情况log往下分
{
if(s==0)
{
return 2;
}
ull l = s-1;
ull len = pow(2, l) + EPS;
if(n <= len)
{
return gao(l,n);
}
else
{
return d[s-1]+2*gao(l,n-len);//2倍关系平移
}
}
ull getAns(ull x)//这样算很好写。lr类型的都这样写
{
if(x==0)
return 0;
if(x==1)
{
return 2;
}
if(x==2)
{
return 4;
}
ull k;
for(ull i = 1;;i++)
{
if(pow(2,i)-EPS <= x)
{
k = i;
}
else
{
break;
}
}
ull ans = 0;
for(ull i = 0;i < k;i++)
{
ans += d[i];
}
ull start = (pow(2,k)+EPS);
ull n = x - start + 1;
ans += gao(k, n);
return ans;
}
ull x, y;
void solve()
{
ull ans = getAns(y) + 1;
if(x!=0)
{
ans -= (getAns(x-1)+1);
}
printf("%llu\n", ans);
}
int main()
{
// freopen("13Min.txt", "r", stdin);
//freopen("1out.txt", "w", stdout);
getD();
while(scanf("%llu%llu", &x, &y) != EOF)
{
if(x==0&&y==0)
{
break;
}
solve();
}
return 0;
}