题目链接:哆啦A梦传送门
题意:给出三个函数:
q次询问,每个输出w(x,y)的结果。
题解:
这题可以通过一系列的化简得到最简表达式。先给出结论,再解释。
对于询问 w(x,y) :首先我们 令len=y-x+1,len2=(y-x)/2+1。
1,假设len为奇数,那么此时w(x,y)等价于
f(x,x)^f(x,x+2)^f(x,x+4)^...^f(x,x+2*i) (x+2*i<=y)
f(x+2,x+2)^f(x+2,x+4)^...^f(x+2,x+2*i) (x+2*i<=y)
f(x+4,x+4)^...^f(x+4,x+2*i) (x+2*i<=y)
f(y,y)。
2,假设len为偶数,那么此时w(x,y)等价于
f(x,x+1)^f(x,x+3)^f(x,x+5)^...^f(x,x+2*i+1) (x+2*i+1<=y)
f(x+2,x+3)^f(x+2,x+5)^...^f(x+2,x+2*i+1) (x+2*i+1<=y)
f(x+4,x+5)^...^f(x+4,x+2*i+1) (x+2*i+1<=y)
f(y-1,y)。
这里是化成第一步,它还可以再消去的,然后我们再分一次奇偶。所以总共有4种情况。
one:len为奇数,len2也为奇数,w(x,y)= ax^a(x+4)^...^ay。
two:len为奇数,len2为偶数, w(x,y)=a(x+1)^a(x+1+4)^...^a(y-1)。
three:len为偶数,len2为奇数,w(x,y)=ax^a(x+4)^...^ay^a(x+1)^a(x+1+4)^...^a(y-1)。
four:len为偶数,len2为偶数,w(x,y)=0。
故我们只需预处理扫一遍就可以 O(1)解决了。
现在我们解释一下是怎么通过判断len的奇偶性来找到上三角的呢?很简单,想几个数据,对着9*9乘法表一直化简。
例如:w(3,7),它等价于下面所有函数的异或
列:
1 2 3 4 5
g(3,3) g(3,4) g(3,5) g(3,6) g(3,7)
g(4,4) g(4,5) g(4,6) g(4,7)
g(5,5) g(5,6) g(5,7)
g(6,6) g(6,7)
g(7,7)
我们每列每列的消去,最后得到:
f(3,3) f(3,3) f(3,3) f(3,3) f(3,3)
f(3,4) f(3,4) f(3,4) f(3,4)
f(3,5) f(3,5) f(3,5)
f(5,5) f(3,6) f(3,6)
f(5,5) f(3,7)
f(5,6) f(5,5)
f(5,6)
f(5,7)
f(7,7)
最后我们把这些重复的偶数项给消去,就得到上面的式子了。
#include
#include
#include
using namespace std;
typedef long long LL;
const int maxn=1e5+10;
LL a[maxn],sum[maxn];
///sum[i]表示 a[i]^a[i-4]^...
int main()
{
int ncase,n;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++)
{
if(i<=4) sum[i]=a[i];
else sum[i]=sum[i-4]^a[i];
}
int q,x,y;
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&x,&y);
int len=y-x+1,len2;
LL ans;
if(len%2)
{
len2=(y-x)/2+1;
if(len2%2)
{
ans=sum[y];
if(x>=4)
ans^=sum[x-4];
printf("%lld\n",ans);
}
else{
ans=sum[y-1];
if(x+1>=4)
ans^=sum[x-3];
printf("%lld\n",ans);
}
}
else{
len2=(y-x)/2+1;
if(len2%2)
{
ans=sum[y];
if(x>=4)
ans^=sum[x-4];
// printf("%lld\n",ans);
ans^=sum[y-1];
if(x+1>=4)
ans^=sum[x-3];
printf("%lld\n",ans);
}
else{
puts("0");
}
}
}
}
}