【XSY3313】异或和(xorsum)(结论)

先上一个结论。

  • 一个长度为 n n n 01 01 01 序列,其每个子序列的异或和的和为 [ 序 列 中 包 含 1 ] 2 n − 1 [序列中包含 1]2^{n-1} [1]2n1

证明:考虑若不存在 1 1 1,则显然。否则若存在 1 1 1,随便选一个 1 1 1 出来,不失一般性地设为第 1 1 1 位,然后考虑第 2 ∼ n 2\sim n 2n 位的某个子序列的异或和 s s s,第 1 1 1 位的 1 1 1 有且仅有一种选取方式使得 s s s 变为 1 1 1。故整个序列每个子序列的异或和的和就是第 2 ∼ n 2\sim n 2n 位的子序列个数 2 n − 1 2^{n-1} 2n1

那么按位考虑之后, f ( a 1 , a 2 , ⋯   , a n ) = ( a 1 ∣ a 2 ∣ ⋯ ∣ a n ) × 2 n − 1 f(a_1,a_2,\cdots,a_n)=(a_1|a_2|\cdots|a_n)\times 2^{n-1} f(a1,a2,,an)=(a1a2an)×2n1。于是题目相当于询问从 [ l , r ] [l,r] [l,r] 中选 n n n 个数或起来能得到多少种不同的结果。

再来一个结论。

  • n > 2 n>2 n>2 n = 2 n=2 n=2 没有区别。

证明:

首先 n = 2 n=2 n=2 时得到的结果一定被 n > 2 n>2 n>2 时得到的结果包含,于是我们只需考虑任意一种 n > 2 n>2 n>2 的结果都能被构造成两个数 a , b ∈ [ l , r ] a,b\in[l,r] a,b[l,r] 的或。

l , r l,r l,r 最高不同位为 h h h m i d = 2 h mid=2^{h} mid=2h,那么我们把 [ l , r ] [l,r] [l,r] 分成 [ l , m i d − 1 ] [l,mid-1] [l,mid1](它们第 h h h 位都为 0 0 0)和 [ m i d , r ] [mid,r] [mid,r](它们第 h h h 位都为 1 1 1),考虑 n > 2 n>2 n>2 时的选取情况:

  • 若选了 [ l , m i d − 1 ] [l,mid-1] [l,mid1] 中的某个数,那么 a 1 ∣ a 2 ∣ ⋯ ∣ a n a_1|a_2|\cdots|a_n a1a2an 的第 0 ∼ h − 1 0\sim h-1 0h1 位所组成的数 x x x 一定大于等于 l l l,那么就一定有 x ∈ [ l , m i d − 1 ] x\in [l,mid-1] x[l,mid1],于是先令 a ← x a\gets x ax,然后再视 a 1 ∣ a 2 ∣ ⋯ ∣ a n a_1|a_2|\cdots|a_n a1a2an h h h 位是否为 1 1 1 来考虑 b ← m i d b\gets mid bmid b b b 不选。
  • 若没有选 [ l , m i d − 1 ] [l,mid-1] [l,mid1] 中的任意一个数,即只选了 [ m i d , r ] [mid,r] [mid,r] 中的数。那么设 r r r 除了第 h h h 位以外的最高位为第 h ′ h' h 位( r r r 的次高位),那么 a 1 ∣ a 2 ∣ ⋯ ∣ a n ∈ [ m i d , m i d + 2 h ′ + 1 ) a_1|a_2|\cdots|a_n\in [mid,mid+2^{h'+1}) a1a2an[mid,mid+2h+1),设 a 1 ∣ a 2 ∣ ⋯ ∣ a n a_1|a_2|\cdots|a_n a1a2an 0 ∼ h ′ − 1 0\sim h'-1 0h1 位所组成的数为 x x x,那么先令 a ← m i d + x a\gets mid+x amid+x,然后再视 a 1 ∣ a 2 ∣ ⋯ ∣ a n a_1|a_2|\cdots|a_n a1a2an h ′ h' h 位是否为 1 1 1 来考虑 b ← m i d + 2 h ′ b\gets mid+2^{h'} bmid+2h b b b 不选。

证毕。

证明的过程同时也得到了 a ∣ b a|b ab 的取值范围,于是分类讨论一下即可。

#include<bits/stdc++.h>

#define ll long long

using namespace std;

inline ll read()
{
	ll x=0;
	int f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

int T,n;

inline ll lowbit(ll x)
{
	return x&-x;
}

int main()
{
	T=read();
	while(T--)
	{
		n=read();
		ll l=read(),r=read();
		if(n==1)
		{
			printf("%lld\n",r-l+1);
			continue;
		}
		if(l==r)
		{
			puts("1");
			continue;
		}
		ll y=l^r;
		int hb;
		for(hb=63;hb>=0;hb--)
			if((y>>hb)&1) break;
		ll z=(1ll<<(ll)(hb+1))-1;
		l&=z,r&=z;
		ll mid=(1ll<<(ll)hb);
		ll ans=(mid-l)<<1ll;
		r^=mid;
		int hbb=hb;
		for(;hbb>=0;hbb--)
			if((r>>hbb)&1ll) break;
		ll x=(1ll<<(ll)(hbb+1))-1;
		ans+=min(x,l-1)+1;
		printf("%lld\n",ans);
	}
	return 0;
}
/*
3
3 3 4
2 10 11
3 1 3
*/
/*
1
5 7 33
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值