类欧几里得

【xsy2126】超级绵羊异或 类欧几里德算法

题意

分析

  根据位运算的位独立性,我们逐位考虑当前位的异或值,即分析每一位的个数是有奇数个,还是偶数个。
  我们从最后一位开始进行分析。答案即为

i=0n1((bi+a)mod2)mod2=(i=0n1bi+a)mod2

特殊的,对于第 i 位,答案为
i=0n1(bi+a2imod2)mod2=(i=0n1bi+a2i)mod2

  发现我们要求 O(logn) 个形如

calc(n,a,b,c)=i=0nai+bc
的式子的答案。

  当 ac 或者 bc 时,我们显然可以将原式化简。
  设 a=pc+a,b=qc+b ,则有

calc(n,a,b,c)=i=0nai+bc=i=0npi+q+ai+bc=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=0nai+bc=i=0nj=0m1[j<ai+bc]=i=0nj=0m1[j+1ai+bc]=i=0nj=0m1[cj+cbai]=i=0nj=0m1[cj+cb1<ai]=i=0nj=0m1[i>cj+cb1a]=j=0m1(n+1i=0n[icj+cb1a])=n×mj=0m1cj+cb1a

  边界条件为 a=0 。此时

calc(n,a,b,c)=i=0nbc=(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;
}

你可能感兴趣的:(数论)