結果

問題 No.2849 Birthday Donuts
ユーザー NachiaNachia
提出日時 2024-08-23 22:32:42
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 3,016 ms / 6,000 ms
コード長 12,337 bytes
コンパイル時間 2,088 ms
コンパイル使用メモリ 121,476 KB
実行使用メモリ 509,696 KB
最終ジャッジ日時 2024-08-23 22:33:50
合計ジャッジ時間 66,250 ms
ジャッジサーバーID
(参考情報)
judge1 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2,109 ms
509,488 KB
testcase_01 AC 2,127 ms
509,492 KB
testcase_02 AC 2,261 ms
509,400 KB
testcase_03 AC 2,289 ms
509,372 KB
testcase_04 AC 2,767 ms
509,416 KB
testcase_05 AC 2,835 ms
509,460 KB
testcase_06 AC 2,778 ms
509,512 KB
testcase_07 AC 2,801 ms
509,548 KB
testcase_08 AC 2,802 ms
509,440 KB
testcase_09 AC 2,837 ms
509,448 KB
testcase_10 AC 2,872 ms
509,504 KB
testcase_11 AC 2,867 ms
509,456 KB
testcase_12 AC 2,763 ms
509,340 KB
testcase_13 AC 2,850 ms
509,408 KB
testcase_14 AC 2,813 ms
509,456 KB
testcase_15 AC 2,759 ms
509,440 KB
testcase_16 AC 2,865 ms
509,404 KB
testcase_17 AC 2,781 ms
509,568 KB
testcase_18 AC 2,847 ms
509,300 KB
testcase_19 AC 2,783 ms
509,492 KB
testcase_20 AC 3,016 ms
509,696 KB
testcase_21 AC 2,306 ms
509,480 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

// #ifdef NACHIA
// #define _GLIBCXX_DEBUG
// #else
// #define NDEBUG
// #endif
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using i64 = long long;
using u64 = unsigned long long;
#define rep(i,n) for(int i=0; i<int(n); i++)
const i64 INF = 1001001001001001001;
template<typename A> void chmin(A& l, const A& r){ if(r < l) l = r; }
template<typename A> void chmax(A& l, const A& r){ if(l < r) l = r; }
#include <atcoder/modint>
using Modint = atcoder::static_modint<998244353>;
using namespace std;
#include <cstdint>
#include <utility>

namespace nachia{

int Popcount(unsigned long long c) noexcept {
#ifdef __GNUC__
    return __builtin_popcountll(c);
#else
    c = (c & (~0ull/3)) + ((c >> 1) & (~0ull/3));
    c = (c & (~0ull/5)) + ((c >> 2) & (~0ull/5));
    c = (c & (~0ull/17)) + ((c >> 4) & (~0ull/17));
    c = (c * (~0ull/257)) >> 56;
    return c;
#endif
}

// please ensure x != 0
int MsbIndex(unsigned long long x) noexcept {
#ifdef __GNUC__
    return 63 - __builtin_clzll(x);
#else
    using u64 = unsigned long long;
    int q = (x >> 32) ? 32 : 0;
    auto m = x >> q;
    constexpr u64 hi = 0x8888'8888;
    constexpr u64 mi = 0x1111'1111;
    m = (((m | ~(hi - (m & ~hi))) & hi) * mi) >> 35;
    m = (((m | ~(hi - (x & ~hi))) & hi) * mi) >> 31;
    q += (m & 0xf) << 2;
    q += 0x3333'3333'2222'1100 >> (((x >> q) & 0xf) << 2) & 0xf;
    return q;
#endif
}

// please ensure x != 0
int LsbIndex(unsigned long long x) noexcept {
#ifdef __GNUC__
    return __builtin_ctzll(x);
#else
    return MsbIndex(x & -x);
#endif
}

}


namespace nachia{

template<class PosX, class PosY, class Val>
struct RectangleSum{
private:

struct BitVectorRank {
    using u64 = std::uint64_t;
    using u32 = std::uint32_t;
    
    std::vector<std::pair<u64, u32>> a;
    BitVectorRank(const std::vector<bool>& b = {}){
        int n = b.size();
        a.assign(n/64 + 1, std::make_pair((u64)0, (u32)0));
        auto p = b.begin();
        u32 sum = 0;
        u64 tmp = 0;
        for(int i=0; i<=n; i+=64){
            tmp = 0;
            int maxd = std::min<int>(n - i, 64);
            for(int d=0; d<maxd; d++){
                tmp |= (u64)(*p ? 1 : 0) << d;
                ++p;
            }
            a[i/64] = std::make_pair(tmp, sum);
            sum += Popcount(tmp);
        }
    }
    std::uint32_t rank(std::uint32_t i) const {
        auto [b, s] = a[i >> 6];
        return (u32)(Popcount(b & ~(~u64(0) << (i & 63)))) + s;
    }
    bool get(std::uint32_t i) const { return (a[i >> 6].first >> (i & 63)) & 1; }
};
    
    int n;
    int N;
    int logN;
    std::vector<PosX> Xsorted;
    std::vector<PosY> Ysorted;
    std::vector<int> rankX;
    std::vector<std::vector<Val>> ds;
    std::vector<int> Z;
    std::vector<BitVectorRank> L;
    Val ZERO;
    
    void construct(const std::vector<std::pair<std::pair<PosX, PosY>, Val>>& val){
        n = val.size();

        std::vector<std::pair<PosX,PosY>> pos(n);
        for(int i=0; i<n; i++) pos[i] = val[i].first;

        std::vector<int> sortIY(n);
        for(int i=0; i<n; i++) sortIY[i] = i;
        std::sort(sortIY.begin(),sortIY.end(),[&pos](int l,int r){
            return pos[l].second < pos[r].second; });
        Ysorted.resize(n);
        for(int i=0; i<n; i++) Ysorted[i] = pos[sortIY[i]].second;

        std::vector<int> sortIX(n);
        rankX.resize(n);
        for(int i=0; i<n; i++) sortIX[i] = i;
        std::sort(sortIX.begin(),sortIX.end(),[&pos](int l,int r){
            return pos[l]<pos[r]; });
        Xsorted.resize(n);
        for(int i=0; i<n; i++) Xsorted[i] = pos[sortIX[i]].first;
        for(int i=0; i<n; i++) rankX[sortIX[i]] = i;

        N = 1; logN = 0;
        while(N < n){ N *= 2; logN++; }
        ds.assign(logN+1, std::vector<Val>(n+1, ZERO));
        L.resize(logN);
        Z.resize(logN);
        std::vector<int> Idx = sortIY;
        for(int k=0; k<n; k++) ds[logN][k+1] = ds[logN][k] + val[Idx[k]].second;
        for(int i=logN-1; i>=0; i--){
            std::vector<bool> Lbuf(n,0);
            std::vector<int> preIdx(n); std::swap(preIdx, Idx);
            int z = ((n >> (i+1)) << i) + std::min(1<<i, (n % (2 << i)));
            Z[i] = z;
            int ai = 0, bi = z;
            for(int k=0; k<n; k++){
                bool chooseb = rankX[preIdx[k]] & (1<<i);
                if(!chooseb) Idx[ai++] = preIdx[k];
                else Idx[bi++] = preIdx[k];
                Lbuf[k] = !chooseb;
            }
            for(int k=0; k<n; k++) ds[i][k+1] = ds[i][k] + val[Idx[k]].second;
            L[i] = BitVectorRank(Lbuf);
        }

        for(int i=0; i<n; i++) rankX[sortIY[i]] = i;
    }

public:

    RectangleSum(const std::vector<std::pair<std::pair<PosX, PosY>, Val>>& val, Val Zero)
        : ZERO(Zero) {
        construct(val);
    }

    RectangleSum(const std::vector<std::pair<PosX, PosY>>& points, const std::vector<Val>& vals, Val Zero)
        : ZERO(Zero) {
        n = vals.size();
        std::vector<std::pair<std::pair<PosX, PosY>, Val>> buf;
        for(int i=0; i<n; i++) buf.emplace_back(points[i], vals[i]);
    }

    Val sumByIndex(int xl, int xr, int yl, int yr){
        Val ans = ZERO;
        if(xl >= xr || yl >= yr) return ans;
        struct Search{ int i, xa, xb, ys, yt; };
        std::vector<Search> Q;
        Q.reserve((logN+1)*2);
        Q.push_back({ logN,0,n,yl,yr });
        for(int i=0; i<(int)Q.size(); i++){
            auto p = Q[i];
            if(p.xa == p.xb) continue;
            if(xl <= p.xa && p.xb <= xr){
                ans += ds[p.i][p.yt] - ds[p.i][p.ys];
                continue;
            }
            p.i--;
            int nxs = L[p.i].rank(p.ys), nxt = L[p.i].rank(p.yt);
            int xm = p.xa+(1<<p.i);
            if(xl < xm) Q.push_back({ p.i,p.xa,xm,nxs,nxt });
            if(xm < xr) Q.push_back({ p.i,xm,p.xb,Z[p.i]+p.ys-nxs,Z[p.i]+p.yt-nxt });
        }
        return ans; 
    }
  
    Val sum(PosX xl, PosX xr, PosY yl, PosY yr){
        return sumByIndex(
            lower_bound(Xsorted.begin(),Xsorted.end(),xl) - Xsorted.begin(),
            lower_bound(Xsorted.begin(),Xsorted.end(),xr) - Xsorted.begin(),
            lower_bound(Ysorted.begin(),Ysorted.end(),yl) - Ysorted.begin(),
            lower_bound(Ysorted.begin(),Ysorted.end(),yr) - Ysorted.begin()
        );
    }

    Val sumLUByIndex(int xr, int yr){
        if(xr == n) return ds[logN][yr];
        Val ans = ZERO;
        int xa = 0, xb = n, ys = 0, yt = yr;
        for(int i=logN; i>=1; ){
            if(xa == xb) break;
            i--;
            int nxs = L[i].rank(ys), nxt = L[i].rank(yt);
            int xm = xa + (1<<i);
            if(xr < xm){
                xb = xm; ys = nxs; yt = nxt;
            } else {
                ans += ds[i][nxt] - ds[i][nxs];
                xa = xm; ys = Z[i]+ys-nxs; yt = Z[i]+yt-nxt;
            }
        }
        return ans; 
    }
  
    Val sumLU(PosX xr, PosY yr){
        return sumLUByIndex(
            lower_bound(Xsorted.begin(),Xsorted.end(),xr) - Xsorted.begin(),
            lower_bound(Ysorted.begin(),Ysorted.end(),yr) - Ysorted.begin()
        );
    }
};

} // namespace nachia
#include <cassert>



namespace nachia{

namespace prime_sieve_explicit_internal{
    std::vector<bool> isprime = { false }; // a[x] := isprime(2x+1)

    void CalcIsPrime(int z){
        if((int)isprime.size() *2+1 < z+1){
            int new_z = isprime.size();
            while(new_z*2+1 < z+1) new_z *= 2;
            z = new_z-1;
            isprime.resize(z+1, true);
            for(int i=1; i*(i+1)*2<=z; i++) if(isprime[i]){
                for(int j=i*(i+1)*2; j<=z; j+=i*2+1) isprime[j] = false;
            }
        }
    }
    
    std::vector<int> prime_list = {2};
    int prime_list_max = 0;

    void CalcPrimeList(int z){
        while((int)prime_list.size() < z){
            if((int)isprime.size() <= prime_list_max + 1) CalcIsPrime(prime_list_max * 2 + 10);
            for(int p=prime_list_max+1; p<(int)isprime.size(); p++){
                if(isprime[p]) prime_list.push_back(p*2+1);
            }
            prime_list_max = isprime.size() - 1;
        }
    }

    void CalcPrimeListUntil(int z){
        if(prime_list_max < z){
            CalcIsPrime(z);
            for(int p=prime_list_max+1; p<(int)isprime.size(); p++){
                if(isprime[p]) prime_list.push_back(p*2+1);
            }
            prime_list_max = isprime.size() - 1;
        }
    }

}


bool IsprimeExplicit(int n){
    using namespace prime_sieve_explicit_internal;
    if(n == 2) return true;
    if(n % 2 == 0) return false;
    CalcIsPrime(n);
    return isprime[(n-1)/2];
}

int NthPrimeExplicit(int n){
    using namespace prime_sieve_explicit_internal;
    CalcPrimeList(n);
    return prime_list[n];
}

int PrimeCountingExplicit(int n){
    using namespace prime_sieve_explicit_internal;
    if(n < 2) return 0;
    CalcPrimeListUntil(n);
    auto res = std::upper_bound(prime_list.begin(), prime_list.end(), n) - prime_list.begin();
    return (int)res;
}

// [l, r)
std::vector<bool> SegmentedSieveExplicit(long long l, long long r){
    assert(0 <= l); assert(l <= r);
    long long d = r - l;
    if(d == 0) return {};
    std::vector<bool> res(d, true);
    for(long long p=2; p*p<=r; p++) if(IsprimeExplicit(p)){
        long long il = (l+p-1)/p, ir = (r+p-1)/p;
        if(il <= p) il = p;
        for(long long i=il; i<ir; i++) res[i*p-l] = false;
    }
    if(l < 2) for(long long p=l; p<2 && p<r; p++) res[l-p] = false;
    return res;
}


} // namespace nachia

namespace nachia{

template<class Elem>
void DivisorZeta(std::vector<Elem>& a){
    int n = a.size() - 1;
    for(int d=2; d<=n; d++) if(IsprimeExplicit(d)) for(int i=1; i*d<=n; i++) a[i*d] += a[i];
}

template<class Elem>
void DivisorReversedZeta(std::vector<Elem>& a){
    int n = a.size() - 1;
    for(int d=2; d<=n; d++) if(IsprimeExplicit(d)) for(int i=n/d; i>=1; i--) a[i] += a[i*d];
}

template<class Elem>
void DivisorMobius(std::vector<Elem>& a){
    int n = a.size() - 1;
    for(int d=2; d<=n; d++) if(IsprimeExplicit(d)) for(int i=n/d; i>=1; i--) a[i*d] -= a[i];
}

template<class Elem>
void DivisorReversedMobius(std::vector<Elem>& a){
    int n = a.size() - 1;
    for(int d=2; d<=n; d++) if(IsprimeExplicit(d)) for(int i=1; i*d<=n; i++) a[i] -= a[i*d];
}

template<class Elem>
std::vector<Elem> GcdConvolution(std::vector<Elem> a, std::vector<Elem> b){
    assert(a.size() == b.size());
    assert(1 <= a.size());
    DivisorReversedZeta(a);
    DivisorReversedZeta(b);
    for(int i=1; i<(int)a.size(); i++) a[i] *= b[i];
    DivisorReversedMobius(a);
    return a;
}

template<class Elem>
std::vector<Elem> LcmConvolution(std::vector<Elem> a, std::vector<Elem> b){
    assert(a.size() == b.size());
    assert(1 <= a.size());
    DivisorZeta(a);
    DivisorZeta(b);
    for(int i=1; i<(int)a.size(); i++) a[i] *= b[i];
    DivisorMobius(a);
    return a;
}

template<class Elem>
void SumForCoprimeIndex(std::vector<Elem>& f){
    if((int)f.size() <= 1) return;
    Elem q = f[1];
    for(int i=2; i<(int)f.size(); i++) q += f[i];
    std::vector<int> F(f.size()); F[1] = -1;
    DivisorMobius(F);
    DivisorReversedZeta(f);
    f[1] -= f[1];
    Elem t = f[1];
    for(int i=2; i<(int)f.size(); i++){
        if(F[i] == 0) f[i] = f[1];
        if(F[i] == -1){ t = f[1]; t -= f[i]; f[i] = t; }
    }
    DivisorZeta(f);
    for(int i=1; i<(int)f.size(); i++){ t = q; t -= f[i]; f[i] = t; }
}

} // namespace nachia

void testcase(){
    int Z = 200000;
    vector<int> Q(Z+1);
    for(int i=1; i<=Z; i++) Q[i] = i-1;
    nachia::DivisorMobius(Q);
    vector<pair<int,int>> pos;
    vector<i64> weight;
    vector<pair<pair<int,int>, i64>> pw;
    for(int p=2; p<=Z; p++) for(int q=2; q*p<=Z; q++){
        pos.push_back({ p*q-p, p*q });
        weight.push_back(Q[p]);
        pw.push_back({ pos.back(), weight.back() });
    }
    auto md = nachia::RectangleSum<int,int,i64>(pw, 0);
    int T; cin >> T;
    i64 ansxor = 0;
    rep(t,T){
        i64 l,r; cin >> l >> r; l ^= ansxor; r ^= ansxor;
        i64 s = md.sum(l, r+1, l, r+1);
        i64 ans = r*(r-1)/2 - (l-1)*(l-2)/2 - s;
        ansxor = ans;
        cout << ans << '\n';
    }
}

int main(){
    ios::sync_with_stdio(false); cin.tie(nullptr);
    testcase();
    return 0;
}
0