1. 程式人生 > 實用技巧 >JZOJ5149 超級綿羊異或 - 異或 + 類歐幾里得

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;
}