提出 #66961847


ソースコード 拡げる

#include <iostream>
#include <string>
#include <sstream>
#include <iomanip> 
#include <math.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <complex>
#include <functional>
#include <numeric>

using namespace std;


#define MP make_pair
#define PB push_back
#define F first
#define S second
#define LB lower_bound
#define UB upper_bound
#define SZ(x) ((int)x.size())
#define LEN(x) ((int)x.length())
#define ALL(x) begin(x), end(x)
#define RSZ resize
#define ASS assign
#define REV(x) reverse(x.begin(), x.end());
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define F0R(i, a) for (int i = 0; i < (a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= (a); i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)
#define trav(a, x) for (auto& a : x)
typedef long long LL;
typedef pair<LL, LL> PL;
typedef vector<LL> VL;
typedef vector<PL> VPL;
typedef vector<VL> VVL;
typedef vector<VVL> VVVL;
typedef vector<VVVL> VVVVL;
typedef vector<string> VS;
typedef pair<int, int> PI;
typedef vector<int> VI;
typedef vector<PI> VPI;
typedef vector<vector<int>> VVI;
typedef vector<vector<PI>> VVPI;

typedef long double LD;
typedef pair<LD, LD> PLDLD;

typedef complex<double> CD;
typedef vector<CD> VCD;



const LL INF = 1E18;
const int MAXX = 300005;
const LD PAI = 4 * atan((LD)1);



template <typename T>
class fenwick_tree {
public:
    vector<T> fenw;
    int n;

    fenwick_tree(int _n) : n(_n) {
        fenw.resize(n);
    }

    fenwick_tree() {

    }

    void initialize(int _n) {
        fenw.assign(_n, 0);
        n = _n;
    }

    void update(int x, T v) {
        while (x < n) {
            fenw[x] += v;
            x |= (x + 1);
            //x += (x & (-x));
        }
    }

    T query(int x) {
        T v{};
        while (x >= 0) {
            v += fenw[x];
            x = (x & (x + 1)) - 1;
        }
        return v;
    }

    T query_full(int a, int b) {		// range query
        if ((a == 0) || (b == 0) || (a > b)) return 0;
        return query(b) - ((a <= 1) ? 0 : query(a - 1));
    }
};


template <typename T>
class segment_tree {
    vector<T> t;
    T VERYBIG;
    bool ISMAXRANGE;
    int size;
public:
    segment_tree(int n, bool range_max = true) {
        if (is_same<T, int>::value) VERYBIG = (1 << 30);
        else if (is_same<T, LL>::value) VERYBIG = (1LL << 60);
        //else if (is_same<T, PII>::value) VERYBIG = PII({ 1E9, 1E9 });
        //else if (is_same<T, PLL>::value) VERYBIG = { 1LL << 60, 1LL << 60 };

        ISMAXRANGE = range_max;

        if (ISMAXRANGE) t.assign(4 * n + 1, 0);
        else t.assign(4 * n + 1, VERYBIG);
        size = n;
    }

    void initialize_array(vector<T>& v) {
        initialize_with_array(1, 0, size - 1, v);
    }

    void initialize_with_array(int startpos, int l, int r, vector<T>& v) {
        if (l == r) {
            t[startpos] = v[l];
        }
        else {
            int m = (l + r) / 2;
            initialize_with_array(2 * startpos, l, m, v);
            initialize_with_array(2 * startpos + 1, m + 1, r, v);

            if (ISMAXRANGE == 1) t[startpos] = max(t[startpos * 2], t[startpos * 2 + 1]);
            else  t[startpos] = min(t[startpos * 2], t[startpos * 2 + 1]);
        }
    }

    void update(int index, T val) { // insert val into location index
        update_full(1, 0, size - 1, index, val);
    }

    void update_full(int startpos, int l, int r, int index, T val) {
        if (l == r) {
            t[startpos] = val;
        }
        else {
            int m = (l + r) / 2;
            if (index <= m) update_full(2 * startpos, l, m, index, val);
            else update_full(2 * startpos + 1, m + 1, r, index, val);

            if (ISMAXRANGE) t[startpos] = max(t[startpos * 2], t[startpos * 2 + 1]);
            else t[startpos] = min(t[startpos * 2], t[startpos * 2 + 1]);
        }
    }

    T query(int l, int r) {  // get range min/max between l and r
        if (l > r) {
            if (ISMAXRANGE) return 0;
            else return VERYBIG;
        }
        return query_full(1, 0, size - 1, l, r);
    }

    T query_full(int startpos, int left, int right, int l, int r) {	 // left/right = current range, l/r = intended query range
        if ((left >= l) && (right <= r)) return t[startpos];
        int m = (left + right) / 2;
        T ans;
        if (ISMAXRANGE) ans = -VERYBIG;
        else ans = VERYBIG;
        if (m >= l) {
            if (ISMAXRANGE) ans = max(ans, query_full(startpos * 2, left, m, l, r));
            else ans = min(ans, query_full(startpos * 2, left, m, l, r));
        }
        if (m + 1 <= r) {
            if (ISMAXRANGE) ans = max(ans, query_full(startpos * 2 + 1, m + 1, right, l, r));
            else ans = min(ans, query_full(startpos * 2 + 1, m + 1, right, l, r));
        }
        return ans;
    }
};

//#define MOD 1000000007
int MODX = 1, root = 2; // 998244353

template<class T> T invGeneral(T a, T b) {
    a %= b; if (a == 0) return b == 1 ? 0 : -1;
    T x = invGeneral(b, a);
    return x == -1 ? -1 : ((1 - (LL)b * x) / a + b) % b;
}

template<class T> struct modular {
    T val;
    explicit operator T() const { return val; }
    modular() { val = 0; }
    modular(const LL& v) {
        val = (-MODX <= v && v <= MODX) ? v : v % MODX;
        if (val < 0) val += MODX;
    }

    friend ostream& operator<<(ostream& os, const modular& a) { return os << a.val; }
    friend bool operator==(const modular& a, const modular& b) { return a.val == b.val; }
    friend bool operator!=(const modular& a, const modular& b) { return !(a == b); }
    friend bool operator<(const modular& a, const modular& b) { return a.val < b.val; }

    modular operator-() const { return modular(-val); }
    modular& operator+=(const modular& m) { if ((val += m.val) >= MODX) val -= MODX; return *this; }
    modular& operator-=(const modular& m) { if ((val -= m.val) < 0) val += MODX; return *this; }
    modular& operator*=(const modular& m) { val = (LL)val * m.val % MODX; return *this; }
    friend modular pow(modular a, LL p) {
        modular ans = 1; for (; p; p /= 2, a *= a) if (p & 1) ans *= a;
        return ans;
    }
    friend modular inv(const modular& a) {
        auto i = invGeneral(a.val, MODX); assert(i != -1);
        return i;
    } // equivalent to return exp(b,MOD-2) if MOD is prime
    modular& operator/=(const modular& m) { return (*this) *= inv(m); }

    friend modular operator+(modular a, const modular& b) { return a += b; }
    friend modular operator-(modular a, const modular& b) { return a -= b; }
    friend modular operator*(modular a, const modular& b) { return a *= b; }

    friend modular operator/(modular a, const modular& b) { return a /= b; }
};

typedef modular<int> mi;
typedef pair<mi, mi> pmi;
typedef vector<mi> vmi;
typedef vector<pmi> vpmi;

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

namespace vecOp {
    template<class T> vector<T> rev(vector<T> v) { reverse(ALL(v)); return v; }
    template<class T> vector<T> shift(vector<T> v, int x) { v.insert(v.begin(), x, 0); return v; }

    template<class T> vector<T>& operator+=(vector<T>& l, const vector<T>& r) {
        l.rSZ(max(SZ(l), SZ(r))); F0R(i, SZ(r)) l[i] += r[i]; return l;
    }
    template<class T> vector<T>& operator-=(vector<T>& l, const vector<T>& r) {
        l.rSZ(max(SZ(l), SZ(r))); F0R(i, SZ(r)) l[i] -= r[i]; return l;
    }
    template<class T> vector<T>& operator*=(vector<T>& l, const T& r) { trav(t, l) t *= r; return l; }
    template<class T> vector<T>& operator/=(vector<T>& l, const T& r) { trav(t, l) t /= r; return l; }

    template<class T> vector<T> operator+(vector<T> l, const vector<T>& r) { return l += r; }
    template<class T> vector<T> operator-(vector<T> l, const vector<T>& r) { return l -= r; }
    template<class T> vector<T> operator*(vector<T> l, const T& r) { return l *= r; }
    template<class T> vector<T> operator*(const T& r, const vector<T>& l) { return l * r; }
    template<class T> vector<T> operator/(vector<T> l, const T& r) { return l /= r; }

    template<class T> vector<T> operator*(const vector<T>& l, const vector<T>& r) {
        if (min(SZ(l), SZ(r)) == 0) return {};
        vector<T> x(SZ(l) + SZ(r) - 1); F0R(i, SZ(l)) F0R(j, SZ(r)) x[i + j] += l[i] * r[j];
        return x;
    }
    template<class T> vector<T>& operator*=(vector<T>& l, const vector<T>& r) { return l = l * r; }

    template<class T> vector<T> rem(vector<T> a, vector<T> b) {
        while (SZ(b) && b.back() == 0) b.pop_back();
        assert(SZ(b)); b /= b.back();
        while (SZ(a) >= SZ(b)) {
            a -= a.back() * shift(b, SZ(a) - SZ(b));
            while (SZ(a) && a.back() == 0) a.pop_back();
        }
        return a;
    }
    template<class T> vector<T> interpolate(vector<pair<T, T>> v) {
        vector<T> ret;
        F0R(i, SZ(v)) {
            vector<T> prod = { 1 };
            T todiv = 1;
            F0R(j, SZ(v)) if (i != j) {
                todiv *= v[i].f - v[j].f;
                vector<T> tmp = { -v[j].f,1 }; prod *= tmp;
            }
            ret += prod * (v[i].s / todiv);
        }
        return ret;
    }
}

using namespace vecOp;

class factorial {
public:
    LL MAXX, MOD;
    VL f, ff;

    factorial(LL maxx = 200010, LL mod = 998244353) {
        MAXX = maxx;
        MOD = mod;

        f.RSZ(MAXX);
        ff.RSZ(MAXX);

        f[0] = 1;
        for (int i = 1; i < MAXX; i++) f[i] = (f[i - 1] * i) % MOD;
        for (int i = 0; i < MAXX; i++) ff[i] = mul_inv(f[i], MOD);
    }

    long long mul_inv(long long a, long long b)
    {
        long long b0 = b, t, q;
        long long x0 = 0, x1 = 1;
        if (b == 1) return 1;
        while (a > 1) {
            q = a / b;
            t = b, b = a % b, a = t;
            t = x0, x0 = x1 - q * x0, x1 = t;
        }
        if (x1 < 0) x1 += b0;
        return x1;
    }

    long long division(long long a, long long b) {		// (a / b) mod p = ((a mod p) * (b^(-1) mod p)) mod p
        long long ans, inv;
        inv = mul_inv(b, MOD);
        ans = ((a % MOD) * inv) % MOD;
        return ans;
    }

    LL calcc(LL n, LL a) {
        if (n == a) return 1;
        if (n == 0) return 0;
        if (n < a) return 0;
        LL ans = (f[n] * ff[a]) % MOD;
        ans = (ans * ff[n - a]) % MOD;
        return ans;
    }

    LL calcp(LL n, LL a) {
        LL ans = (f[n] * ff[n - a]) % MOD;
        return ans;
    }

    LL ball_in_box(LL box, LL ball) {    // # of ways of putting k balls to n boxes; boxes can be empty
        if (box == 0) return (ball == 0);
        LL ans = calcc(ball + box - 1, ball);
        return ans;
    }


    LL exp(LL base, LL n, LL MODD = -1) {
        LL mod;
        if (MODD == -1) mod = MOD;
        else mod = MODD;

        base %= mod;
        LL ans = 1, x = base, MAXLEVEL = 60, i;

        for (i = 0; i < MAXLEVEL; i++) {
            if ((1LL << i) > n) break;
            if ((1LL << i) & n) ans = (ans * x) % mod;
            x = (x * x) % mod;
        }
        return ans;
    }

    LL exp_abc(LL a, LL b, LL c) {  // a ^ (b ^ c) $ MOD where b and c can be very big
        // https://www.geeksforgeeks.org/find-power-power-mod-prime/#
        // Fermat's Little: a ^ (MOD - 1) = 1 % MOD
        // a ^ (b ^ c) % MOD = a ^ (b ^ c % (MOD - 1)) % MOD

        LL bc = exp(b, c, MOD - 1);
        LL ans = exp(a, bc);
        return ans;
    }


    LL sum_arithmetic_sequence(LL first_item, LL difference, LL n) {
        LL ans, last = (first_item + difference * (n - 1)) % MOD;
        ans = ((first_item + last) * n / 2) % MOD;

        return ans;
    }

    LL sum_geometry_sequence(LL first_item, LL ratio, LL n) {
        LL ans;

        if (ratio == 1) ans = (first_item * n) % MOD;
        else if (n == 1) ans = first_item;
        else {
        https://www.mathsisfun.com/algebra/sequences-sums-geometric.html
            LL rn = exp(ratio, n);
            ans = (first_item * (1 - rn + MOD)) % MOD;
            ans = division(ans, 1 - ratio + MOD) % MOD;
        }
        return ans;
    }
};

#ifdef _MSC_VER 
//#include <intrin.h>
#endif

namespace FFT {
#ifdef _MSC_VER 
    int size(int s) {
        if (s == 0) return 0;
        unsigned long index;
        _BitScanReverse(&index, s);
        return index + 1;
    }
#else
    constexpr int size(int s) { return s > 1 ? 32 - __builtin_clz(s - 1) : 0; }
#endif

    template<class T> bool small(const vector<T>& a, const vector<T>& b) {
        return (LL)SZ(a) * SZ(b) <= 500000;
    }

    void genRoots(vmi& roots) { // primitive n-th roots of unity
        int n = SZ(roots); mi r = pow(mi(root), (MODX - 1) / n);
        roots[0] = 1; FOR(i, 1, n) roots[i] = roots[i - 1] * r;
    }
    void genRoots(VCD& roots) { // change cd to complex<double> instead?
        int n = SZ(roots); LD ang = 2 * PAI / n;
        F0R(i, n) roots[i] = CD(cos(ang * i), sin(ang * i)); // is there a way to do this more quickly?
    }

    template<class T> void fft(vector<T>& a, vector<T>& roots) {
        int n = SZ(a);
        for (int i = 1, j = 0; i < n; i++) { // sort by reverse bit representation
            int bit = n >> 1;
            for (; j & bit; bit >>= 1) j ^= bit;
            j ^= bit; if (i < j) swap(a[i], a[j]);
        }
        for (int len = 2; len <= n; len <<= 1)
            for (int i = 0; i < n; i += len)
                F0R(j, len / 2) {
                auto u = a[i + j], v = a[i + j + len / 2] * roots[n / len * j];
                a[i + j] = u + v, a[i + j + len / 2] = u - v;
            }
    }

    template<class T> vector<T> conv(vector<T> a, vector<T> b) {
        //if (small(a, b)) return a * b;
        int s = SZ(a) + SZ(b) - 1, n = 1 << size(s);
        vector<T> roots(n); genRoots(roots);

        a.RSZ(n), fft(a, roots); b.RSZ(n), fft(b, roots);
        F0R(i, n) a[i] *= b[i];
        reverse(begin(roots) + 1, end(roots)); fft(a, roots); // inverse FFT

        T in = T(1) / T(n); trav(x, a) x *= in;
        a.RSZ(s); return a;
    }

    VL conv(const VL& a, const VL& b) {
        //if (small(a, b)) return a * b;
        VCD X = conv(VCD(ALL(a)), VCD(ALL(b)));
        VL x(SZ(X)); F0R(i, SZ(X)) x[i] = round(X[i].real());
        return x;
    } // ~0.55s when SZ(a)=SZ(b)=1<<19

    VL conv(const VL& a, const VL& b, LL mod) { // http://codeforces.com/contest/960/submission/37085144
        //if (small(a, b)) return a * b;
        int s = SZ(a) + SZ(b) - 1, n = 1 << size(s);

        VCD v1(n), v2(n), r1(n), r2(n);
        F0R(i, SZ(a)) v1[i] = CD(a[i] >> 15, a[i] & 32767); // v1(x)=a0(x)+i*a1(x)
        F0R(i, SZ(b)) v2[i] = CD(b[i] >> 15, b[i] & 32767); // v2(x)=b0(x)+i*b1(x)

        VCD roots(n); genRoots(roots);
        fft(v1, roots), fft(v2, roots);
        F0R(i, n) {
            int j = (i ? (n - i) : i);
            CD ans1 = (v1[i] + conj(v1[j])) * CD(0.5, 0); // a0(x)
            CD ans2 = (v1[i] - conj(v1[j])) * CD(0, -0.5); // a1(x)
            CD ans3 = (v2[i] + conj(v2[j])) * CD(0.5, 0); // b0(x)
            CD ans4 = (v2[i] - conj(v2[j])) * CD(0, -0.5); // b1(x)
            r1[i] = (ans1 * ans3) + (ans1 * ans4) * CD(0, 1); // a0(x)*v2(x)
            r2[i] = (ans2 * ans3) + (ans2 * ans4) * CD(0, 1); // a1(x)*v2(x)
        }
        reverse(begin(roots) + 1, end(roots));
        fft(r1, roots), fft(r2, roots); F0R(i, n) r1[i] /= n, r2[i] /= n;

        VL ret(n);
        F0R(i, n) {
            LL av = (LL)round(r1[i].real()); // a0*b0
            LL bv = (LL)round(r1[i].imag()) + (LL)round(r2[i].real()); // a0*b1+a1*b0
            LL cv = (LL)round(r2[i].imag()); // a1*b1
            av %= mod, bv %= mod, cv %= mod;
            ret[i] = (av << 30) + (bv << 15) + cv;
            ret[i] = (ret[i] % mod + mod) % mod;
        }
        ret.resize(s);
        return ret;
    } // ~0.8s when SZ(a)=SZ(b)=1<<19
}
using namespace FFT;

long long gcd(long long a, long long b)
{
    while (b != 0) {
        long long t = b;
        b = a % b;
        a = t;
    }
    return a;
}



class tree {		// implementation of recurvie programming
    int ct;
public:
    int nn, root;				// # of nodes, id of root
    vector<int> parent;			// parent of each node; -1 if unassigned
    vector<int> depth;			// depth of each node
    vector<int> sz;				// subtree size of each node 
    vector<vector<int>> adj;	// adjacency list from each node
    vector<vector<int>> sons;	// sons list from each node

    // for cartesian_decomposition
    vector<int> in, out;		// starting and ending position of a subtree
    vector<int> pos;			// inorder of DFS

    // for LCA sparse table
    vector<vector<int>> pred;
    int MAXLEVEL;

    bool called_LCA = false;

    tree(int n) {
        nn = n;
        adj.clear();
        adj.resize(n);
    }

    void add_path(int a, int b) {
        adj[a].push_back(b);
        adj[b].push_back(a);
    }

    void add_directed_path(int a, int b) {
        adj[a].push_back(b);
    }

    void dfs_set_root(int id, bool cartesian_decomposition = false) {	// internal
        if (cartesian_decomposition) {
            in[id] = ct;
            pos[ct] = id;
            ct++;
        }

        sz[id]++;

        for (auto p : adj[id]) {
            if (parent[p] == -1) {
                parent[p] = id;
                depth[p] = depth[id] + 1;
                dfs_set_root(p, cartesian_decomposition);
                sz[id] += sz[p];

                sons[id].push_back(p);
            }
        }

        if (cartesian_decomposition) out[id] = ct - 1;
    }

    void set_root(int id, bool cartesian_decomposition = true) {		// set root of the tree and calculate necessary info
        if (cartesian_decomposition) {
            in.resize(nn);
            out.resize(nn);
            pos.resize(nn);
            ct = 0;
        }

        parent.assign(nn, -1);
        depth.assign(nn, -1);
        sz.assign(nn, 0);
        sons.clear();
        sons.resize(nn);

        // dfs_set_root(id, cartesian_decomposition);


        // set root using stack
        stack<pair<int, int>> st;		// id, # of sons processes
        st.push({ id, 0 });
        parent[id] = 0;
        depth[id] = 0;

        int ct = 0;

        while (!st.empty()) {
            int id = st.top().first, x = st.top().second;

            if (x == 0) {
                in[id] = ct;
                pos[ct] = id;
                sz[id] = 1;
                ct++;
            }

            if (x >= adj[id].size()) {
                out[id] = ct - 1;
                if (parent[id] != -1) {
                    sz[parent[id]] += sz[id];
                }
                st.pop();
            }
            else {

                st.top().second++;

                int p = adj[id][x];
                if (parent[p] == -1) {
                    parent[p] = id;
                    depth[p] = depth[id] + 1;
                    sons[id].push_back(p);
                    st.push({ p, 0 });
                }
            }
        }

        sz[0] = nn;

        int i = 0;
    }

    void eulerian_tour_dfs(int root, vector<int>& ans) {
        ans.push_back(root);
        for (auto p : sons[root]) {
            eulerian_tour_dfs(p, ans);
            ans.push_back(root);
        }
    }

    vector<int> eulerian_tour(int root) {
        vector<int> ans;

        eulerian_tour_dfs(root, ans);

        return ans;
    }


    void prep_LCA() {		// prepare the sparse table for LCA calculation
        MAXLEVEL = 1;
        while ((1 << MAXLEVEL) < nn) MAXLEVEL++;
        MAXLEVEL++;

        pred.assign(MAXLEVEL, vector<int>(nn, 0));
        pred[0] = parent;

        int i, j, k;
        for (i = 1; i < MAXLEVEL; i++) {
            for (j = 0; j < nn; j++) {
                if (pred[i - 1][j] != -1) pred[i][j] = pred[i - 1][pred[i - 1][j]];
            }
        }

        called_LCA = true;
    }

    int get_p_ancestor(int a, int p) {		// get p-ancestor of node a;  need to call set_root() and prep_LCA() first
        if (!called_LCA) prep_LCA();

        int i;
        for (i = MAXLEVEL - 1; (i >= 0) && (p > 0) && (a != -1); i--) {
            if ((1 << i) & p) {
                p -= (1 << i);
                a = pred[i][a];
            }
        }
        return a;
    }

    int LCA(int a, int b) {		// get the LCA of a and b, need to call set_root() and prep_LCA() first
        if (!called_LCA) prep_LCA();
        int da = depth[a], db = depth[b];

        if (da > db) {
            swap(da, db);
            swap(a, b);
        }

        int i, j, k;
        for (i = MAXLEVEL - 1; i >= 0; i--) {
            if (db - (1 << i) >= da) {
                db -= (1 << i);
                b = pred[i][b];
            }
        }

        if (a == b) return a;

        for (i = MAXLEVEL - 1; i >= 0; i--) {
            if (pred[i][a] != pred[i][b]) {
                a = pred[i][a];
                b = pred[i][b];
            }
        }

        return parent[a];
    }

    int get_distance(int a, int b) {	// get distance between a and b, need to call set_root() and prep_LCA() first
        if (!called_LCA) prep_LCA();

        int c = LCA(a, b);
        int ans = depth[a] + depth[b] - 2 * depth[c];
        return ans;
    }

    int get_diameter(VI& path) {
        int a, b, c, i, j, k, id, INF = nn + 100, ans;
        vector<int> dist(nn), last(nn);
        queue<int> q;

        if (nn == 1) return 0;

        // first pass, start with 1 -- any node
        a = 1;
        dist.assign(nn, INF);
        dist[a] = 0;
        q.push(a);

        while (!q.empty()) {
            id = q.front();
            q.pop();

            for (auto p : adj[id]) {
                if (dist[p] == INF) {
                    dist[p] = dist[id] + 1;
                    q.push(p);
                }
            }
        }

        // second pass, start from the most remote node id, collect last to get ID
        a = id;
        dist.assign(nn, INF);
        last.assign(nn, -1);
        dist[a] = 0;
        q.push(a);

        while (!q.empty()) {
            id = q.front();
            q.pop();

            for (auto p : adj[id]) {
                if (dist[p] == INF) {
                    dist[p] = dist[id] + 1;
                    last[p] = id;
                    q.push(p);
                }
            }
        }

        // a and id forms the diameter
        ans = dist[id];

        //return ans;

        // construct the path of diamter in path
        path.clear();
        b = id;
        c = id;
        do {
            path.push_back(b);
            b = last[b];
        } while (b != -1);

        return ans;
    }
};


// Union-Find Disjoint Sets Library written in OOP manner, using both path compression and union by rank heuristics
// initialize: UnionFind UF(N)

class UnionFind {                                              // OOP style
private:
    vector<int> p, rank, setSize;
    // p = path toward the root of disjoint set; p[i] = i means it is root
    // rank = upper bound of the actual height of the tree; not reliable as accurate measure
    // setSize = size of each disjoint set

    int numSets;
public:
    UnionFind(int N) {
        setSize.assign(N, 1);
        numSets = N;
        rank.assign(N, 0);
        p.assign(N, 0);
        for (int i = 0; i < N; i++) p[i] = i;	// each belongs to its own set
    }

    int findSet(int i) {
        return (p[i] == i) ? i : (p[i] = findSet(p[i]));		// path compression: cut short of the path if possible
    }

    bool isSameSet(int i, int j) {
        return findSet(i) == findSet(j);
    }

    void unionSet(int i, int j) {
        if (!isSameSet(i, j)) {
            numSets--;
            int x = findSet(i), y = findSet(j);
            // rank is used to keep the tree short
            if (rank[x] > rank[y]) { p[y] = x; setSize[x] += setSize[y]; }
            else {
                p[x] = y; setSize[y] += setSize[x];
                if (rank[x] == rank[y]) rank[y]++;
            }
        }
    }

    int numDisjointSets() {		// # of disjoint sets
        return numSets;
    }

    int sizeOfSet(int i) {		// size of set
        return setSize[findSet(i)];
    }
};


#define MAXN 425000			// total # of prime numbers
#define MAXP 3000000		// highest number to test prime

int prime[MAXN];		// prime numbers: 2, 3, 5 ...
int lp[MAXP];		// lp[n] = n if n is prime; otherwise smallest prime factor of the number
int phi[MAXP];			// phii function

class prime_class {
public:
    long top;

    prime_class() {			// generate all prime under MAXP
        int i, i2, j;

        top = 0;
        lp[0] = 0;
        lp[1] = 1;
        for (i = 2; i < MAXP; i++) lp[i] = 0;

        top = 0;
        for (i = 2; i < MAXP; ++i) {
            if (lp[i] == 0) {
                lp[i] = i;
                prime[top++] = i;
            }
            for (j = 0; (j < top) && (prime[j] <= lp[i]) && (i * prime[j] < MAXP); ++j)
                lp[i * prime[j]] = prime[j];
        }
    }

    bool isprime(long long key)
    {
        if (key < MAXP)	return (lp[key] == key) && (key >= 2);
        else {
            int i;
            for (i = 0; (i < top) && (prime[i] * prime[i] <= key); i++)
                if (key % prime[i] == 0) return false;
            return true;
        }
    }

    unordered_map<int, int> factorize(int key) {
        unordered_map<int, int> ans;

        while (lp[key] != key) {
            ans[lp[key]]++;
            key /= lp[key];
        }
        if (key > 1) ans[key]++;

        return ans;
    }

    vector<int> mobius(int n) {     // generate mobius function of size n
        int i, j, k, ct, curr, cct, x, last;
        vector<int> mobius(n + 1);
        for (i = 1; i <= n; i++) {
            curr = i; ct = 0; last = -1;

            while (lp[curr] != curr) {
                x = lp[curr];
                if (x != last) {
                    cct = 1;
                    last = x;
                    ct++;
                }
                else {
                    if (++cct >= 2) {
                        mobius[i] = 0;
                        goto outer;
                    }

                }
                curr /= lp[curr];
            }
            if (curr > 1) {
                x = curr;
                if (x != last) {
                    cct = 1;
                    last = x;
                    ct++;
                }
                else {
                    if (++cct >= 2) {
                        mobius[i] = 0;
                        goto outer;
                    }

                }
            }

            if (ct % 2 == 0) mobius[i] = 1;
            else mobius[i] = -1;

        outer:;
        }

        return mobius;
    }

    int get_phi(int key) {	// calculate Euler's totient function, also known as phi-function
        int ans = key, last = 0;

        while (lp[key] != key) {
            if (lp[key] != last) {
                last = lp[key];
                ans -= ans / last;
            }
            key /= lp[key];
        }
        if ((key > 1) && (key != last)) ans -= ans / key;

        return ans;
    }

    void calc_all_phi(int n) {
        int i, j, k;
        for (int i = 1; i < n; i++) phi[i] = i;
        for (int i = 2; i < n; i++) {
            if (phi[i] == i) {
                for (int j = i; j < n; j += i) {
                    phi[j] /= i;
                    phi[j] *= i - 1;
                }
            }
        }
    }

    vector<pair<long long, long long>> factorize_full(long long key) {		// can be used to factorize numbers >= MAXP
        vector<pair<long long, long long>> ans;

        long i, ct, sq = sqrt(key) + 10;

        for (i = 0; (i < top) && (prime[i] <= sq); i++)
            if (key % prime[i] == 0) {
                ct = 0;
                while (key % prime[i] == 0) {
                    ct++;
                    key /= prime[i];
                }
                ans.push_back({ prime[i], ct });
            }
        if (key > 1) {
            ans.push_back({ key, 1 });
        }
        return ans;
    }

    void generate_divisors(int step, int v, vector<pair<int, int>>& fp, vector<int>& ans) {
        if (step < fp.size()) {
            generate_divisors(step + 1, v, fp, ans);
            for (int i = 1; i <= fp[step].second; i++) {
                v *= fp[step].first;
                generate_divisors(step + 1, v, fp, ans);
            }
        }
        else ans.push_back(v);
    }

    void generate_divisors_full(long long step, long long v, vector<pair<long long, long long>>& fp, vector<long long>& ans) {
        if (step < fp.size()) {
            generate_divisors_full(step + 1, v, fp, ans);
            for (int i = 1; i <= fp[step].second; i++) {
                v *= fp[step].first;
                generate_divisors_full(step + 1, v, fp, ans);
            }
        }
        else ans.push_back(v);
    }

    vector<int> get_divisors(int key) {
        unordered_map<int, int> f = factorize(key);
        int n = f.size();
        vector<pair<int, int>> fp;
        for (auto p : f) fp.push_back(p);
        vector<int> ans;
        generate_divisors(0, 1, fp, ans);
        return ans;
    }

    vector<long long> get_divisors_full(long long key) {
        vector<pair<long long, long long>> f = factorize_full(key);
        int n = f.size();
        vector<pair<long long, long long>> fp;
        for (auto p : f) fp.push_back(p);
        vector<long long> ans;
        generate_divisors_full(0, 1, fp, ans);
        return ans;
    }


    long long get_divisors_count(long long key) {
        vector<pair<long long, long long>> f = factorize_full(key);
        long long ans = 1;
        for (auto p : f) ans *= (p.second + 1);
        return ans;
    }

};


long long mul_inv(long long a, long long b)
{
    long long b0 = b, t, q;
    long long x0 = 0, x1 = 1;
    if (b == 1) return 1;
    while (a > 1) {
        q = a / b;
        t = b, b = a % b, a = t;
        t = x0, x0 = x1 - q * x0, x1 = t;
    }
    if (x1 < 0) x1 += b0;
    return x1;
}

long long division(long long a, long long b, long long p) {		// (a / b) mod p = ((a mod p) * (b^(-1) mod p)) mod p
    long long ans, inv;
    inv = mul_inv(b, p);
    ans = ((a % p) * inv) % p;
    return ans;
}


template <typename T>
class serializer {
public:
    map<T, T> id;
    vector<T> value;

    vector<T> serialize(vector<T> a, int startvalue = 0) {
        int n = a.size(), i, j, k, ct;
        vector<T> ans(n);
        for (auto p : a) id[p] = 0;
        if (startvalue == 1) value.push_back(-1);
        ct = startvalue;
        for (auto p : id) {
            value.push_back(p.first);
            id[p.first] = ct++;
        }
        for (i = 0; i < n; i++) ans[i] = id[a[i]];
        return ans;
    }
};


#define MP make_pair
#define PB push_back
#define F first
#define S second
#define LB lower_bound
#define UB upper_bound

#define SZ(x) ((int)x.size())
#define LEN(x) ((int)x.length())
#define ALL(x) begin(x), end(x)
#define RSZ resize
#define ASS assign
#define REV(x) reverse(x.begin(), x.end());

#define MAX(x) *max_element(ALL(x))
#define MIN(x) *min_element(ALL(x))
#define FOR(i, n) for (int i = 0; i < n; i++) 
#define FOR1(i, n) for (int i = 1; i <= n; i++) 
#define SORT(x) sort(x.begin(), x.end())
#define RSORT(x) sort(x.rbegin(), x.rend())
#define SUM(x) accumulate(x.begin(), x.end(), 0LL)


#define IN(x) cin >> x;
#define OUT(x) cout << (x) << "\n";
#define INV(x, n) FOR(iiii, n) { cin >> x[iiii]; }
#define INV1(x, n) FOR1(iiii, n) { cin >> x[iiii]; }
#define OUTV(x, n) { FOR(iiii, n) { cout << x[iiii] << " "; } cout << "\n"; }
#define OUTVV(x) OUTV(x, x.size());
#define OUTA OUT(ans);
#define OUTVA OUTV(ans, ans.size());
#define OUTV1(x, n) { FOR1(iiii, n) { cout << x[iiii] << " "; } cout << "\n"; }
#define OUTVV1(x) OUTV1(x, x.size() - 1);
#define OUTV1A OUTVV1(ans); 
#define OUTYN(x) { if (x) cout << "YES\n"; else cout << "NO\n"; }
#define OUTyn(x) { if (x) cout << "Yes\n"; else cout << "No\n"; }


#define MOD7 1000000007
#define MOD9 1000000009
#define MOD3 998244353

#define MMAX(n, x)  n = max(n, x)
#define MMIN(n, x)  n = min(n, x)

#define MAXNN 20
#define MAXNNN (1LL << 20) 

//LL dp[MAXNNN][MAXNN];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    LL n, m, i, j, k, ans, MOD = MOD3, u, v, nn;

    cin >> n >> m;
    VVL ct(n, VL(n, 0));
    FOR(i, m) {
        cin >> u >> v;
        u--; v--;
        ct[u][v]++;
        ct[v][u]++;
    }
    nn = 1LL << n;

    VL popc(nn, 0), mind(nn, 0);
    FOR1(i, nn - 1) {
        FOR(j, n) {
            if ((1LL << j) & i) {
                popc[i] = 1 + popc[i ^ (1LL << j)];
                mind[i] = j;
                break;
            }
        }
    }

    VVL dp(nn, VL(n, 0));

    // dp[bitmask][curr] = count of ways;  // [min node to start] implied in bitmask
    FOR(i, n) dp[1LL << i][i] = 1;

    ans = 0;
    // multi-edge
    FOR(i, n) {
        for (j = i + 1; j < n; j++) {
            if (ct[i][j] > 1) ans = (ans + ct[i][j] * (ct[i][j] - 1)) % MOD;
        }
    }


    FOR1(mask, nn - 1) {
        FOR(curr, n) {
            if (dp[mask][curr] == 0) continue;
            if (popc[mask] > 2) {
                // new cycle found
                ans = (ans + dp[mask][curr] * ct[curr][mind[mask]]) % MOD;
            }
            for (k = mind[mask] + 1; k < n; k++) {
                if (ct[curr][k]) {
                    LL mask2 = mask ^ (1LL << k);
                    dp[mask2][k] = (dp[mask2][k] + dp[mask][curr] * ct[curr][k]) % MOD;
                }
            }
        }
    }

    // dedup
    ans = division(ans, 2, MOD);

    OUTA;

    return 0;
}




提出情報

提出日時
問題 G - Count Cycles
ユーザ wjli
言語 C++ 20 (gcc 12.2)
得点 600
コード長 35026 Byte
結果 AC
実行時間 601 ms
メモリ 224372 KiB

コンパイルエラー

Main.cpp:1100: warning: "FOR" redefined
 1100 | #define FOR(i, n) for (int i = 0; i < n; i++)
      | 
Main.cpp:38: note: this is the location of the previous definition
   38 | #define FOR(i, a, b) for (int i = (a); i < (b); i++)
      | 
Main.cpp: In member function ‘LL factorial::sum_geometry_sequence(LL, LL, LL)’:
Main.cpp:398:9: warning: label ‘https’ defined but not used [-Wunused-label]
  398 |         https://www.mathsisfun.com/algebra/sequences-sums-geometric.html
      |         ^~~~~
Main.cpp: In member function ‘void tree::set_root(int, bool)’:
Main.cpp:613:19: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<int>::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  613 |             if (x >= adj[id].size()) {
      |                 ~~^~~~~~~~~~~~~~~~~
Main.cpp:636:13: warning: unused variable ‘i’ [-Wunused-variable]
  636 |         int i = 0;
      |             ^
Main.cpp: In member function ‘void tree::prep_LCA()’:
Main.cpp:664:19: warning: unused variable ‘k’ [-Wunused-variable]
  664 |         int i, j, k;
      |                   ^
Main.cpp: In member function ‘int tree::LCA(int, int)’:
Main.cpp:696:16: warning: unused variable ‘j’ [-Wunused-variable]
  696 |         int i, j, k;
      |                ^
Main.cpp:696:19: warning: unused variable ‘k’ [-Wunused-variable]
  696 |         int i, j, k;
      |                   ^
Main.cpp: In member function ‘int tree::get_diameter(VI&)’:
Main.cpp:725:19: warning: variable ‘c’ set but not used [-Wunused-but-set-variable]
  725 |         int a, b, c, i, j, k, id, INF = nn + 100, ans;
      |                   ^
Main.cpp:725:22: warning: unused variable ‘i’ [-Wunused-variable]
  725 |         int a, b, c, i, j, k, id, INF = nn + 100, ans;
      |                      ^
Main.cpp:725:25: warning: unused variable ‘j’ [-Wunused-variable]
  725 |         int a, b, c, i, j, k, id, INF = nn + 100, ans;
      |                         ^
Main.cpp:725:28: warning: unused variable ‘k’ [-Wunused-variable]
  725 |         int a, b, c, i, j, k, id, INF = nn + 100, ans;
      |                            ^
Main.cpp: In constructor ‘prime_class::prime_class()’:
Main.cpp:851:16: warning: unused variable ‘i2’ [-Wunused-variable]
  851 |         int i, i2, j;
      |                ^~
Main.cpp: In member function ‘std::vector<int> prime_class::mobius(int)’:
Main.cpp:893:16: warning: unused variable ‘j’ [-Wunused-variable]
  893 |         int i, j, k, ct, curr, cct, x, last;
      |                ^
Main.cpp:893:19: warning: unused variable ‘k’ [-Wunused-variable]
  893 |         int i, j, k, ct, curr, cct, x, last;
      |                   ^
Main.cpp: In member function ‘void prime_class::calc_all_phi(int)’:
Main.cpp:955:13: warning: unused variable ‘i’ [-Wunused-variable]
  955 |         int i, j, k;
      |             ^
Main.cpp:955:16: warning: unused variable ‘j’ [-Wunused-variable]
  955 |         int i, j, k;
      |                ^
Main.cpp:955:19: warning: unused variable ‘k’ [-Wunused-variable]
  955 |         int i, j, k;
      |                   ^
Main.cpp: In member function ‘void prime_class::generate_divisors(int, int, std::vector<std::pair<int, int> >&, std::vector<int>&)’:
Main.cpp:988:18: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  988 |         if (step < fp.size()) {
      |             ~~~~~^~~~~~~~~~~
Main.cpp: In member function ‘void prime_class::generate_divisors_full(long long int, long long int, std::vector<std::pair<long long int, long long int> >&, std::vector<long long int>&)’:
Main.cpp:999:18: warning: comparison of integer expressions of different signedness: ‘long long int’ and ‘std::vector<std::pair<long long int, long long int> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  999 |         if (step < fp.size()) {
      |             ~~~~~^~~~~~~~~~~
Main.cpp: In member function ‘std::vector<int> prime_class::get_divisors(int)’:
Main.cpp:1011:13: warning: unused variable ‘n’ [-Wunused-variable]
 1011 |         int n = f.size();
      |             ^
Main.cpp: In member function ‘std::vector<long long int> prime_class::get_divisors_full(long long int)’:
Main.cpp:1021:13: warning: unused variable ‘n’ [-Wunused-variable]
 1021 |         int n = f.size();
      |             ^
Main.cpp: In function ‘int main()’:
Main.cpp:1139:14: warning: unused variable ‘i’ [-Wunused-variable]
 1139 |     LL n, m, i, j, k, ans, MOD = MOD3, u, v, nn;
      |              ^

ジャッジ結果

セット名 Sample All
得点 / 配点 0 / 0 600 / 600
結果
AC × 3
AC × 40
セット名 テストケース
Sample 00_sample_00.txt, 00_sample_01.txt, 00_sample_02.txt
All 00_sample_00.txt, 00_sample_01.txt, 00_sample_02.txt, 01_random_00.txt, 01_random_01.txt, 01_random_02.txt, 01_random_03.txt, 01_random_04.txt, 01_random_05.txt, 01_random_06.txt, 01_random_07.txt, 01_random_08.txt, 01_random_09.txt, 01_random_10.txt, 01_random_11.txt, 02_random2_00.txt, 02_random2_01.txt, 02_random2_02.txt, 02_random2_03.txt, 02_random2_04.txt, 02_random2_05.txt, 02_random2_06.txt, 02_random2_07.txt, 03_random3_00.txt, 03_random3_01.txt, 03_random3_02.txt, 03_random3_03.txt, 04_random4_00.txt, 04_random4_01.txt, 05_random5_00.txt, 05_random5_01.txt, 06_random6_00.txt, 06_random6_01.txt, 06_random6_02.txt, 06_random6_03.txt, 07_handmade_00.txt, 07_handmade_01.txt, 07_handmade_02.txt, 07_handmade_03.txt, 07_handmade_04.txt
ケース名 結果 実行時間 メモリ
00_sample_00.txt AC 1 ms 3528 KiB
00_sample_01.txt AC 1 ms 3484 KiB
00_sample_02.txt AC 1 ms 3440 KiB
01_random_00.txt AC 115 ms 54248 KiB
01_random_01.txt AC 9 ms 3608 KiB
01_random_02.txt AC 11 ms 8504 KiB
01_random_03.txt AC 136 ms 224272 KiB
01_random_04.txt AC 311 ms 224272 KiB
01_random_05.txt AC 233 ms 224312 KiB
01_random_06.txt AC 588 ms 224356 KiB
01_random_07.txt AC 589 ms 224264 KiB
01_random_08.txt AC 599 ms 224268 KiB
01_random_09.txt AC 600 ms 224268 KiB
01_random_10.txt AC 601 ms 224264 KiB
01_random_11.txt AC 599 ms 224276 KiB
02_random2_00.txt AC 147 ms 224272 KiB
02_random2_01.txt AC 149 ms 224260 KiB
02_random2_02.txt AC 170 ms 224348 KiB
02_random2_03.txt AC 355 ms 224368 KiB
02_random2_04.txt AC 460 ms 224260 KiB
02_random2_05.txt AC 528 ms 224264 KiB
02_random2_06.txt AC 559 ms 224252 KiB
02_random2_07.txt AC 580 ms 224248 KiB
03_random3_00.txt AC 150 ms 224316 KiB
03_random3_01.txt AC 149 ms 224272 KiB
03_random3_02.txt AC 149 ms 224312 KiB
03_random3_03.txt AC 149 ms 224328 KiB
04_random4_00.txt AC 149 ms 224260 KiB
04_random4_01.txt AC 148 ms 224348 KiB
05_random5_00.txt AC 149 ms 224272 KiB
05_random5_01.txt AC 149 ms 224372 KiB
06_random6_00.txt AC 146 ms 224368 KiB
06_random6_01.txt AC 471 ms 224268 KiB
06_random6_02.txt AC 564 ms 224320 KiB
06_random6_03.txt AC 586 ms 224260 KiB
07_handmade_00.txt AC 1 ms 3488 KiB
07_handmade_01.txt AC 11 ms 3472 KiB
07_handmade_02.txt AC 144 ms 224132 KiB
07_handmade_03.txt AC 147 ms 224260 KiB
07_handmade_04.txt AC 599 ms 224332 KiB