先上一个结论。
- 一个长度为 n n n 的 01 01 01 序列,其每个子序列的异或和的和为 [ 序 列 中 包 含 1 ] 2 n − 1 [序列中包含 1]2^{n-1} [序列中包含1]2n−1。
证明:考虑若不存在 1 1 1,则显然。否则若存在 1 1 1,随便选一个 1 1 1 出来,不失一般性地设为第 1 1 1 位,然后考虑第 2 ∼ n 2\sim n 2∼n 位的某个子序列的异或和 s s s,第 1 1 1 位的 1 1 1 有且仅有一种选取方式使得 s s s 变为 1 1 1。故整个序列每个子序列的异或和的和就是第 2 ∼ n 2\sim n 2∼n 位的子序列个数 2 n − 1 2^{n-1} 2n−1。
那么按位考虑之后, 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)=(a1∣a2∣⋯∣an)×2n−1。于是题目相当于询问从 [ 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,mid−1](它们第 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,mid−1] 中的某个数,那么 a 1 ∣ a 2 ∣ ⋯ ∣ a n a_1|a_2|\cdots|a_n a1∣a2∣⋯∣an 的第 0 ∼ h − 1 0\sim h-1 0∼h−1 位所组成的数 x x x 一定大于等于 l l l,那么就一定有 x ∈ [ l , m i d − 1 ] x\in [l,mid-1] x∈[l,mid−1],于是先令 a ← x a\gets x a←x,然后再视 a 1 ∣ a 2 ∣ ⋯ ∣ a n a_1|a_2|\cdots|a_n a1∣a2∣⋯∣an 第 h h h 位是否为 1 1 1 来考虑 b ← m i d b\gets mid b←mid 或 b b b 不选。
- 若没有选 [ l , m i d − 1 ] [l,mid-1] [l,mid−1] 中的任意一个数,即只选了 [ 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}) a1∣a2∣⋯∣an∈[mid,mid+2h′+1),设 a 1 ∣ a 2 ∣ ⋯ ∣ a n a_1|a_2|\cdots|a_n a1∣a2∣⋯∣an 第 0 ∼ h ′ − 1 0\sim h'-1 0∼h′−1 位所组成的数为 x x x,那么先令 a ← m i d + x a\gets mid+x a←mid+x,然后再视 a 1 ∣ a 2 ∣ ⋯ ∣ a n a_1|a_2|\cdots|a_n a1∣a2∣⋯∣an 第 h ′ h' h′ 位是否为 1 1 1 来考虑 b ← m i d + 2 h ′ b\gets mid+2^{h'} b←mid+2h′ 或 b b b 不选。
证毕。
证明的过程同时也得到了 a ∣ b a|b a∣b 的取值范围,于是分类讨论一下即可。
#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
*/