链接:https://ac.nowcoder.com/acm/contest/941/A
来源:牛客网
题目描述
Pi 有一个 n * n 的表格
第 x 行第 y 列写着正整数 x+y-1
m 次询问,每次给出 xl, yl, xr, yr
求第 xl 行到第 xr 行中第 yl 列到第 yr 列这 (xr-xl+1)*(yr-yl+1) 个正整数的异或和
输入描述:
第一行两个正整数 n, m
接下来 m 行每行四个正整数依次为 xl, yl, xr, yr
保证 1≤xl≤xr≤n, 1≤yl≤yr≤n
输出描述:
m 行
每行一个正整数为所求的异或和
示例1
输入
3 1
1 2 2 3
输出
6
说明
(2 ^ 3 ^ 3 ^ 4)==6
备注:
50%
n≤1000,
m≤10000
70%
n≤1000000,
m≤20000
100%
n≤10^9,
m≤2∗10^5
解题思路:
先求出(1,1) 到(x,y)矩阵元素异或和,用容斥可得答案;
方便起见x
if x & 1:
(Σ(x+1, y-1): i ++i) ^ (Σ(1, x): i i+=2) ^ (Σ(y, x+y-1): i i+=2)
else:
(Σ(1, x-1): i i+=2) ^ (Σ(y+1, x+y-1): i i+=2)
至于连续数字或连续奇数的异或和也是找规律发现与 %4有关
代码:
#include
using namespace std;
typedef long long ll;
namespace io{
const int SIZE=1e7+10;
char inbuff[SIZE];
char *l,*r;
inline void init(){
l=inbuff,r=inbuff+fread(inbuff,1,SIZE,stdin);
}
inline char gc(){
if(l==r)init();
return(l!=r)?*(l++):EOF;
}
void read(ll &x){
x=0;char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))x=x*10+(ch^48),ch=gc();
}
}using io::read;
ll all(ll n){
ll t=n;
n%=4;
if(n==0)return t;
if(n==1)return 1;
if(n==2)return t+1;
return 0;
}
ll odd(ll n){
ll t=n;
n=(n+1)%8;
if(n==0)return 0;
if(n==2)return t;
if(n==4)return 2;
return t+2;
}
ll even(ll n){
if(n&1)return all(n)^odd(n);
else return all(n)^odd(n-1);
}
ll lr(ll a,ll b){
if(a==b)return odd(a+b-1);
if(a>b)swap(a,b);
if(a&1){
ll ans=0,res=0;
if(b>=a+2)ans=all(b-1)^all(a);
if(b&1)res=odd(a+b-1)^odd(b-2);
else res=even(a+b-1)^even(b-2);
return odd(a)^res^ans;
}else{
ll res=0;
if(b&1)res=even(a+b-1)^even(b-1);
else res=odd(a+b-1)^odd(b-1);
return odd(a-1)^res;
}
}
int main(){
ll n,m;read(n),read(m);
while(m--){
ll a,b,c,d;read(a),read(b),read(c),read(d);
if(a>c)swap(a,c);
if(b>d)swap(b,d);
ll ans=(lr(c,d)^lr(a-1,d)^lr(c,b-1)^lr(a-1,b-1));
printf("%lld\n",ans);
}
return 0;
}