JZOJ5149 超级绵羊异或 - 异或 + 类欧几里得

对于异或来说,某一位的数字1出现的次数如果是奇数次,那么偶数个1就会进行异或变成0,还剩下一个1,那么1无论和几个0进行异或都是1
也就是说只需要计算每一位出现的次数是奇数还是偶数,奇数的话,那么就表示答案该位为1,否则为0

对于每一位的统计,
第k位的贡献值是\(\lfloor\frac{a + bi}{2^k} \rfloor \mod 2\)
也就是变成了类欧几里得模板
时间复杂度\(O(62logn)\)

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
const int mod = 2;
ll f(ll a, ll b, ll c, ll n) {
    ll ans = 0;
    if(!a) ans = (b / c) * (n + 1) % mod;
    else if(a >= c || b >= c) {
        ll pre = f(a % c, b % c, c, n);
        ans = (pre + n * (n + 1) / 2 % mod * (a / c) % mod + (n + 1) * (b / c) % mod) % mod;
    }else {
        ll m = (a * n + b) / c;
        ll pre = f(c, c - b - 1, a, m - 1);
        ans = (n * (m % mod) % mod - pre + mod) % mod;
    }
    return ans;
}
void solve(){
    ll a, b, n;
    scanf("%lld%lld%lld", &n, &a, &b);
    ll ans = 0;
    for(int i = 0; i <= 62; i++) {
        ll base = 1ll << i;
        ll x = f(b, a, base, n - 1);
        if(x == 1) ans += base;
    }
    cout << ans << endl;
}
int main(){
    int t; cin >> t;
    while(t--) solve();
    return 0;
}
posted @ 2020-08-24 16:02  Emcikem  阅读(131)  评论(0编辑  收藏  举报