Submission #1063360

#TimeUsernameProblemLanguageResultExecution timeMemory
1063360jer033디지털 회로 (IOI22_circuit)C++17
100 / 100
803 ms24512 KiB
#include "circuit.h"
#include <vector>
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD =  1'000'002'022;
const ll totient = 497758632;//a^(totient-1) = inv(a)

int n, m;
vector<ll> storage;//When you call the constructor, make sure that everything is reduced modulo MOD
vector<int> a;

ll pow(ll a, ll b)
{
    if (b==0ll)
        return 1;
    ll c = pow(a, b/2ll);
    c = (c*c)%MOD;
    if (((b/2ll)*(2ll)) != b)//b is odd
        c = (c*a)%MOD;
    return c;
}

ll inv(ll a)
{
    return pow(a, totient-1ll);
}

class Lazy{
public:
    int L, R;
    ll total_sum;
    ll active;//MAKE SURE THAT THIS IS ALWAYS ACCURATE
    bool flip;//When I need to flip, I don't need to flip myself, I need to flip my children only
    Lazy* left;
    Lazy* right;

    Lazy()
    {
        L = 0; R = 0;
        total_sum = 0; active = 0; flip = 0;
        left = nullptr; right = nullptr;
    }

    Lazy(int l, int r)
    {
        L = l; R = r;
        flip = 0;
        if (L==R)
        {
            left = nullptr;
            right = nullptr;
            total_sum = storage[L];
            if (a[L] == 1)
                active = total_sum;
            else
                active = 0;
        }
        else
        {
            int mid = (l+r)/2;
            left = new Lazy(l, mid);
            right = new Lazy(mid+1, r);
            total_sum = left->total_sum + right->total_sum;
            active = left->active + right->active;
        }
    }

    void update()
    {
        //assumption: My children could have just updated themselves, and so should I
        if (left!=nullptr)
            active = left->active + right->active;
    }

    void pancake_flip()
    {
        //assumption: this is updated, and I want to update myself
        active = total_sum - active;
        if (flip == 0)
            flip = 1;
        else
            flip = 0;
    }

    void push_down()
    {
        //assumption: this is updated, and I want to update my children
        if (flip == 1)
        {
            flip = 0;
            if (left != nullptr)
            {
                left->pancake_flip();
                right->pancake_flip();
            }
        }
    }

    void range_flip(int range_l, int range_r)
    {
        int intersect_l = max(range_l, L);
        int intersect_r = min(range_r, R);
        if ((intersect_l == L) and (intersect_r==R))
        {
            pancake_flip();
            push_down();
        }
        else if (intersect_l <= intersect_r)
        {
            push_down();
            left->range_flip(range_l, range_r);
            right->range_flip(range_l, range_r);
            update();
        }
    }
};

Lazy circ = Lazy();

struct factor{
public:
    ll mn;
    ll f2;
    ll f223;

    factor()
    {
        mn = 1;
        f2 = 0;
        f223 = 0;
    }

    factor(ll a, ll b, ll c)
    {
        mn = a;
        f2 = b;
        f223 = c;
    }
    
    factor(ll n)
    {
        //call this constructor for the degrees
        f2 = 0;
        f223 = 0;
        while ((n%2)==0)
        {
            n = n/2;
            f2++;
        }
        while ((n%223)==0)
        {
            n = n/223;
            f223++;
        }
        mn = n;
    }

    ll conv()
    {
        ll bb = pow(2ll, f2);
        ll cc = pow(223ll, f223);
        ll ans = (mn*bb)%MOD;
        ans = (ans*cc)%MOD;
        return ans;
    }

};

factor multiply(factor x, factor y)
{
    ll a = (x.mn * y.mn)%MOD;
    ll b = (x.f2 + y.f2);
    ll c = (x.f223 + y.f223);
    factor ans = factor(a, b, c);
    return ans;
}

factor divide(factor x, factor y)
{
    ll d = inv(y.mn);
    factor mult = factor(d, 0ll-y.f2, 0ll-y.f223);
    return multiply(x, mult);
}

void init(int N, int M, std::vector<int> P, std::vector<int> A) {
    n = N;
    m = M;
    vector<ll> degrees(N, 0);
    for (int i=1; i<(N+M); i++)
        degrees[P[i]]++;
    vector<factor> orig(N);
    for (int i=0; i<N; i++)
        orig[i] = factor(degrees[i]);
    vector<factor> prods(N);
    prods[0] = orig[0];
    for (int i=1; i<N; i++)
        prods[i] = multiply(prods[i-1], orig[i]);
    vector<factor> quots(N);
    quots[0] = divide(prods[N-1], orig[0]);
    for (int i=1; i<N; i++)
        quots[i] = divide(quots[P[i]], orig[i]);

    for (int i=N; i<(N+M); i++)
    {
        storage.push_back(quots[P[i]].conv());
    }

    //NOTES: Fill in storage with the appropriate values! Initially it is empty. 
    //MAKE SURE TO REDUCE ALL VALLUES MODULO MOD, THANK YOU!
    a = A;
    circ = Lazy(0, M-1);
}

int count_ways(int L, int R) {
    L -= n;
    R -= n;
    circ.range_flip(L, R);
    ll fa = circ.active%MOD;
    int ffa = fa;
    return ffa;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...