连续异或的结果
题目
https://codeforces.com/contest/2225/problem/D
大概意思就是,给你一段数字,要求你选取的这段数字里必须包含x,且这段数字的异或和是0
核心原理

所以题目就变成了,求这段数字中有多少个0x-1中有多少数字对4取模是1,xn中有多少数字对4取模是1,然后前面的数字*后面的数字就是总共有多少种,后面求模完之后是0的也是这样的
代码
#include<bits/stdc++.h>
using namespace std;
const long long MOD=998244353;
long long count0(long long a, long long b){
if(a>b) return 0;
long long res=0;
if(a==0){res++; a=1;}
if(a>b) return res;
long long first=a+((3-a%4)+4)%4;//寻找第一个对4取模之后答案是3的数字
if(first<=b) res+=(b-first)/4+1;//然后看在这个区间里有多少个数字也满足对4取模之后答案是3,用等差数列的方法
return res%MOD;
}
long long count1(long long a, long long b){
if(a>b) return 0;
long long first=a+((1-a%4)+4)%4;
if(first<=b) return ((b-first)/4+1)%MOD;
return 0;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
long long n,x;
scanf("%lld %lld",&n,&x);
//你可能会问,不是从1开始的吗?怎么变成了从0开始的,
//假设我们求出了 k和j是对4取模之后余数为1/0的两个点,那么这段区间的异或和就是f[j]^f[k-1]
//从0开始不会影响异或的结果的,因为多异或一个0不会影响结果的,从0开始就是为了让1~n都有机会当左端点,不然的话,假设x=1
//那么就变成count(1,0),那就直接是0了,因为直接return 0嘛,但是事实不是0,这个显而易见的,第二个例子就是x=1的啊
//而且上面的例子给的也是从0开始的
//其实这个就是一个结论,直接记住就好了
long long A0=count0(0,x-1);
long long B0=count0(x,n);
long long A1=count1(0,x-1);
long long B1=count1(x,n);
printf("%lld\n",(A0*B0+A1*B1)%MOD);
}
}

浙公网安备 33010602011771号