【xsy2126】超级绵羊异或 类欧几里德算法
题意
分析
根据位运算的位独立性,我们逐位考虑当前位的异或值,即分析每一位的个数是有奇数个,还是偶数个。
我们从最后一位开始进行分析。答案即为
∑i=0n−1((bi+a)mod2)mod2=(∑i=0n−1bi+a)mod2
特殊的,对于第 i 位,答案为
发现我们要求 O(logn) 个形如
calc(n,a,b,c)=∑i=0n⌊ai+bc⌋
的式子的答案。
当
a≥c
或者
b≥c
时,我们显然可以将原式化简。
设
a=pc+a′,b=qc+b′
,则有
calc(n,a,b,c)=∑i=0n⌊ai+bc⌋=∑i=0n⌊pi+q+a′i+b′c⌋=pn(n+1)2+q(n+1)+calc(n,a′,b′,c)
当
a<c
且
b<c
时,记
m=⌊an+bc⌋
,则有
calc(n,a,b,c)=∑i=0n⌊ai+bc⌋=∑i=0n∑j=0m−1[j<⌊ai+bc⌋]=∑i=0n∑j=0m−1[j+1≤⌊ai+bc⌋]=∑i=0n∑j=0m−1[cj+c−b≤ai]=∑i=0n∑j=0m−1[cj+c−b−1<ai]=∑i=0n∑j=0m−1[i>⌊cj+c−b−1a⌋]=∑j=0m−1(n+1−∑i=0n[i≤⌊cj+c−b−1a⌋])=n×m−∑j=0m−1⌊cj+c−b−1a⌋
边界条件为 a=0 。此时
calc(n,a,b,c)=∑i=0n⌊bc⌋=(n+1)⌊bc⌋
代码
#include <iostream>
using namespace std;
#define LL long long
const int B=61;
LL nT;
LL n,a,b;
inline LL odd(LL x) {
if (x<0) x=-x;
return x&1;
}
inline LL binom(LL n) {
return odd(n*(n+1)/2);
}
LL calc(LL n,LL a,LL b,LL c) {
if (!a) {
LL sum=odd(n+1)*odd(b/c);
return odd(sum);
}
else if (a>=c||b>=c) {
LL _a=a%c,p=(a-_a)/c;
LL _b=b%c,q=(b-_b)/c;
LL sum=odd(p)*binom(n)+odd(q*(n+1))+calc(n,_a,_b,c);
return odd(sum);
}
else {
LL m=(a*n+b)/c;
LL sum=odd((n)*m)-calc(m-1,c,c-b-1,a);
return odd(sum);
}
}
int main(void) {
#ifndef ONLINE_JUDGE
freopen("sdchr.in","r",stdin);
// freopen("sdchr.out","w",stdout);
#endif
for (cin>>nT;nT>0;nT--) {
cin>>n>>a>>b;
LL sum=0;
for (int i=0;i<=B;i++)
sum|=(calc(n-1,b,a,1ll<<i)<<i);
cout<<sum<<endl;
}
return 0;
}