对于第一种操作,我们枚举枚举Lowbit=1<<0,1<<1,1<<2在1-R和1到1-(L-1)中分别有多少个数,再乘以lowbit(区间长度),然后相减,注意要判断R和L-1是否有枚举的lowbit这一位,来准确计算有多少数,R/lowbit的意思就是把最后几位为0,lowbit为1,前面剩下的位数到0的个数就是所求值了,比如要求1--12中有多少个末尾是100的,那么1100-100=1,那么剩下的位数有0到1两种选择,而如果是求1--9中的,1001-100=1,然而因为1001&100==0,那么1这个选择就不行,那么只有0这个选择。
第二种操作就是求有多少个lowbit包含x,比如10101101=173,1-256中就有10101101,10101110,10110000,11000000,100000000这5个包含,反正就是把末尾全部去掉变成0,而且当前这位lowbit在x中也是0,且比n小,就对答案有贡献。
考场上写了一万年,最后发现问题只剩5分钟了,就没写完
#include<bits/stdc++.h>
using namespace std;
long long n,q;
inline void prework()
{}
void print(__int128 x)
{
if (x>9) print(x/10);
putchar('0'+x%10);
}
inline void mainwork()
{
__int128 ans=0;
long long opt,x,l,r,mi,cnt,upmi,low,low2,num,num2;
for(int i=1;i<=q;i++)
{
scanf("%lld",&opt);
if(opt==1)
{
scanf("%lld%lld",&l,&r);
mi=2ll;ans=0;
for(int j=0;j<=62 && (1ll<<j)<=r;j++)
{
mi=1ll<<j;
if(r&mi)
cnt=r/(mi*2)+1;
else
cnt=r/(mi*2);
if((l-1)&mi)
cnt-=(l-1)/(mi*2)+1;
else
cnt-=(l-1)/(mi*2);
ans+=cnt*mi;
}
}
else
{
scanf("%lld",&x);
upmi=1;low=x&(-x);num=x-low;
while(upmi*2<=x)
upmi<<=1;
ans=1;low<<=1;
if(num!=0)
{
while(low<upmi)
{
if(low&num)
num^=low;
else
{
if(low+num<=n)
ans++;
else
break;
}
low<<=1;
}
}
mi=upmi<<1;
while(mi<=x)
mi<<=1ll;
while(mi<=n)
{
ans++;
mi<<=1ll;
}
}
print(ans);
printf("\n");
//printf("%lld\n",ans);
}
}
int main()
{
while(~scanf("%lld%lld",&n,&q))
{
prework();
mainwork();
}
return 0;
}