제출 #1183939

#제출 시각아이디문제언어결과실행 시간메모리
1183939browntoadSprinkler (JOI22_sprinkler)C++20
0 / 100
4126 ms781824 KiB
#include <bits/stdc++.h>
using namespace std;
#define ll long long 
// #define int ll
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define REP(i, n) FOR(i, 0, n) 
#define REP1(i, n) FOR(i, 1, n+1)
#define RREP(i, n) for (int i = (n)-1; i >= 0; i--)
#define pii pair<int, int>
#define f first
#define s second
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) (int)((x).size())
#define pb push_back
#define endl '\n'
#define IOS() ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)

const ll maxn = 2e5+5;

int n, mod, q;
vector<int> g[maxn];
vector<int> H(maxn);

ll pw(ll a, ll p){
    ll ret = 1;
    while(p > 0){
        if (p & 1){
            ret *= a;
            ret %= mod;
        }
        a *= a;
        a %= mod;
        p >>= 1;
    }
    return ret;
}
ll inv(ll a){
    return pw(a, mod-2);
}

const int mxdis = 40;

int eptr = 0;
int Bv[41][10][2*maxn];
int Av[41][2*maxn];
int Btot[41][10][maxn];
int Atot[41][maxn];

// centroid decomposition
vector<bool> isrem(maxn); // removed?
vector<int> preeid[maxn], precent[maxn], dis[maxn]; // eid connecting previous centroid - this centroid, previous centroid. last precent is itself
vector<int> sz(maxn); 


int find_sz(int u, int pre){
    sz[u] = 1;
    for (auto v:g[u]){
        if (v != pre && !isrem[v]) sz[u] += find_sz(v, u);
    }
    return sz[u];
}
int find_centroid(int u, int expsz, int pre){
    for (auto v:g[u]){
        if (!isrem[v] && v != pre && sz[v]*2 > expsz){
            return find_centroid(v, expsz, u);
        }
    }    
    return u;
}

void centupd(int u, int peid, int pecent, int cd, int pre){
    preeid[u].pb(peid);
    precent[u].pb(pecent);
    dis[u].pb(cd);
    for (auto v:g[u]){
        if (!isrem[v] && v != pre){
            centupd(v, peid, pecent, cd+1, u);
        }
    }

}
void decomposition(int u){
    int cent = find_centroid(u, find_sz(u, -1), -1);
    isrem[cent] = 1;
    precent[cent].pb(cent);
    for (auto v:g[cent]){
        if (!isrem[v]){
            centupd(v, eptr++, cent, 1, cent);
            decomposition(v);
        }
    }
}

vector<int> sieve(maxn), prim;
vector<int> specp;

void modify(int U, int D, int W){
    ll A = 1;
    vector<int> B(SZ(specp));
    if (W == 0){
        B[0] = 1;
    }
    else{
        REP1(i, SZ(specp)-1){
            while(W%specp[i] == 0){
                B[i]++;
                W /= specp[i];
            }
        }
        A = W;
    }
    REP(i, SZ(precent[U])){
        int u = precent[U][i]; // centroid id
        if (u == U){
            Atot[D][u] = (Atot[D][u] * A)%mod;
            REP(k, SZ(specp)) Btot[D][k][u] += B[k];
        }
        else{
            int eid = preeid[U][i], dd = D-dis[U][i];
            if (dd < 0) continue;

            Atot[dd][u] = (Atot[dd][u] * A)%mod;
            Av[dd][eid] = (Av[dd][eid] * A)%mod;
            REP(k, SZ(specp)){
                Btot[dd][k][u] += B[k];
                Bv[dd][k][eid] += B[k];
            }
        }
    }

}
int query(int U){
    ll A = 1, Ainv = 1;
    vector<int> B(SZ(specp));
    REP(i, SZ(precent[U])){
        int u = precent[U][i];
        if (u == U){
            FOR(k, 0, mxdis+1){
                A = (A * Atot[k][u])%mod;
                REP(p, SZ(specp)) B[p] += Btot[k][p][u];
            }
        }
        else{
            int eid = preeid[U][i], dd = dis[U][i];
            FOR(k, dd, mxdis+1){
                A = (A * Atot[k][u])%mod;
                Ainv = (Ainv * Av[k][eid])%mod;
                REP(p, SZ(specp)){
                    B[p] += Btot[k][p][u];
                    B[p] -= Bv[k][p][eid];
                }
            }
        }
    }
    if (B[0] > 0) return 0;
    A *= inv(Ainv);
    A %= mod;
    REP1(i, SZ(specp)-1){
        A = (A * pw(specp[i], B[i]) % mod);
    }
    A = (A * H[U])%mod;
    return A;
}

signed main(){
    IOS();
    cin>>n>>mod;
    specp.pb(0);
    int tmod = mod;
    FOR(i, 2, maxn){
        if (!sieve[i]) prim.pb(i);
        for (int j = i+i; j < maxn; j += i) sieve[j] = 1;
    }
    for (auto v:prim){
        if (tmod%v == 0){
            while(tmod%v == 0) tmod/=v;
            specp.pb(v);
        }
    }
    if (tmod > 1) specp.pb(tmod);

    REP(i, mxdis+1){
        REP(j, maxn){
            Atot[i][j] = 1;
        }
        REP(j, 2*maxn){
            Av[i][j] = 1;
        }
    }

    REP(i, n-1){
        int u, v; cin>>u>>v;
        g[u].pb(v); g[v].pb(u);
    }
    REP1(i, n) cin>>H[i];
    decomposition(1);

    cin>>q;
    REP(i, q){
        int t; cin>>t;
        if (t == 1){
            int a, b, c; cin>>a>>b>>c;
            modify(a, b, c);
        }
        else{
            int x; cin>>x;
            cout<<query(x)<<endl;
        }
    }
}
/*
4 7
1 2
2 3
3 4
1
1
1
1

11
1 2 1 2
1 1 0 2
2 1
2 2
2 3
2 4
1 4 10 2
2 1
2 2
2 3
2 4
*/
#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...