HDU5975

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liufengwei1/article/details/82930591

对于第一种操作,我们枚举枚举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;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/82930591
hdu