結果
問題 | No.2294 Union Path Query (Easy) |
ユーザー | Daylight |
提出日時 | 2023-05-06 13:17:46 |
言語 | D (dmd 2.106.1) |
結果 |
AC
|
実行時間 | 1,755 ms / 4,000 ms |
コード長 | 16,805 bytes |
コンパイル時間 | 2,964 ms |
コンパイル使用メモリ | 236,880 KB |
実行使用メモリ | 392,244 KB |
最終ジャッジ日時 | 2024-06-22 17:54:09 |
合計ジャッジ時間 | 68,554 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
6,812 KB |
testcase_01 | AC | 2 ms
6,812 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 1,635 ms
388,604 KB |
testcase_04 | AC | 1,115 ms
256,696 KB |
testcase_05 | AC | 1,049 ms
234,756 KB |
testcase_06 | AC | 1,525 ms
390,984 KB |
testcase_07 | AC | 1,553 ms
392,244 KB |
testcase_08 | AC | 1,742 ms
385,684 KB |
testcase_09 | AC | 1,755 ms
386,324 KB |
testcase_10 | AC | 1,588 ms
391,244 KB |
testcase_11 | AC | 1,517 ms
391,612 KB |
testcase_12 | AC | 1,516 ms
390,684 KB |
testcase_13 | AC | 1,657 ms
387,660 KB |
testcase_14 | AC | 1,374 ms
391,208 KB |
testcase_15 | AC | 1,336 ms
391,092 KB |
testcase_16 | AC | 1,340 ms
387,980 KB |
testcase_17 | AC | 1,401 ms
385,112 KB |
testcase_18 | AC | 1,426 ms
386,852 KB |
testcase_19 | AC | 1,403 ms
388,072 KB |
testcase_20 | AC | 1,367 ms
387,600 KB |
testcase_21 | AC | 1,569 ms
389,192 KB |
testcase_22 | AC | 1,587 ms
382,776 KB |
testcase_23 | AC | 1,476 ms
386,944 KB |
testcase_24 | AC | 1,407 ms
386,656 KB |
testcase_25 | AC | 2 ms
6,944 KB |
testcase_26 | AC | 1 ms
6,940 KB |
testcase_27 | AC | 2 ms
6,940 KB |
testcase_28 | AC | 580 ms
35,620 KB |
testcase_29 | AC | 670 ms
72,968 KB |
testcase_30 | AC | 717 ms
96,452 KB |
testcase_31 | AC | 743 ms
124,180 KB |
testcase_32 | AC | 777 ms
123,552 KB |
testcase_33 | AC | 822 ms
142,880 KB |
testcase_34 | AC | 876 ms
173,684 KB |
testcase_35 | AC | 945 ms
203,820 KB |
testcase_36 | AC | 1,016 ms
218,712 KB |
testcase_37 | AC | 1,067 ms
234,464 KB |
testcase_38 | AC | 1,097 ms
249,320 KB |
testcase_39 | AC | 1,189 ms
262,496 KB |
testcase_40 | AC | 1,240 ms
262,696 KB |
testcase_41 | AC | 1,280 ms
262,952 KB |
testcase_42 | AC | 1,522 ms
275,972 KB |
testcase_43 | AC | 1,423 ms
305,608 KB |
testcase_44 | AC | 1,466 ms
335,892 KB |
testcase_45 | AC | 1,519 ms
331,256 KB |
testcase_46 | AC | 1,574 ms
361,668 KB |
testcase_47 | AC | 1,704 ms
387,436 KB |
testcase_48 | AC | 1,377 ms
390,060 KB |
ソースコード
public import std; DList!string scan_buffer; DList!char char_buffer; static this() { scan_buffer = DList!(string)(); char_buffer = DList!(char)(); } void cin()() { } void cin(T, A...)(ref T a, ref A tail) { import std.traits : isArray; static if (typeof(a).stringof == "string") { if (!char_buffer.empty) { a = char_buffer.array.map!(x => x.to!string).join(); char_buffer.clear(); } else { while (scan_buffer.empty) { foreach (t; readln.split) { if (t.length == 0) { continue; } scan_buffer.insert(t); } } auto token = scan_buffer.front; scan_buffer.removeFront(); a = token; } } else static if (typeof(a).stringof == "char") { if (!char_buffer.empty) { a = char_buffer.front(); char_buffer.removeFront(); } else { while (scan_buffer.empty) { foreach (t; readln.split) { if (t.length == 0) { continue; } scan_buffer.insert(t); } } auto token = scan_buffer.front; scan_buffer.removeFront(); a = token[0]; if (token.length > 1) { foreach (c; token[1 .. $]) { char_buffer.insertBack(c); } } } } else static if (typeof(a).stringof == "char[]") { if (a.length == 0) { string token; cin(token); foreach (c; token) { a ~= c; } } else { foreach (ref v; a) { cin(v); } } } else static if (isArray!(typeof(a))) { foreach (ref v; a) { cin(v); } } else static if (isTuple!(typeof(a))) { foreach (i, _; a) { cin(a[i]); } } else { if (!char_buffer.empty) { writeln(char_buffer.array.map!(x => x.to!string)); a = char_buffer.array.map!(x => x.to!string).join().to!T; char_buffer.clear(); } else { while (scan_buffer.empty) { foreach (t; readln.split) { if (t.length == 0) { continue; } scan_buffer.insert(t); } } auto token = scan_buffer.front; scan_buffer.removeFront(); a = token.to!T; } } cin(tail); } bool chmin(T)(ref T a, T b) { if (a > b) { a = b; return true; } return false; } bool chmax(T)(ref T a, T b) { if (a < b) { a = b; return true; } return false; } alias PQueue(T = long, alias less = "a<b") = BinaryHeap!(Array!T, less); class PotentialUnionFind(S, alias op, alias e, alias inv) { import std; private: static if (is(typeof(e) : string)) { auto unit() { return mixin(e); } } else { alias unit = e; } int treeCnt; int[] p; S[] potential; int N; public: this(int size) { N = size; p = new int[](N); p[] = -1; potential = new S[](N); potential[] = unit(); treeCnt = N; } bool same(int x, int y) { return leader(x) == leader(y); } int merge(int x, int y, S w) { w = binaryFun!(op)(w, getPotential(x)); w = binaryFun!(op)(w, unaryFun!(inv)(getPotential(y))); return link(leader(x), leader(y), w); } private: int link(int x, int y, S w) { if (x == y) return x; if (p[x] > p[y]) { swap(x, y); w = unaryFun!(inv)(w); } p[x] += p[y]; p[y] = x; treeCnt--; potential[y] = w; return x; } public: int leader(int x) { if (p[x] < 0) { return x; } else { int l = leader(p[x]); potential[x] = binaryFun!(op)(potential[x], potential[p[x]]); return p[x] = l; } } S getPotential(int x) { leader(x); return potential[x]; } S diff(int x, int y) { return binaryFun!(op)(getPotential(y), unaryFun!(inv)(getPotential(x))); } int countTree() { return treeCnt; } int size(int a) { return -p[leader(a)]; } } import std.typecons : Tuple; ulong safeMod(long x, long m) @safe pure nothrow @nogc { x %= m; if (x < 0) x += m; return x; } ulong[2] umul128(ulong a, ulong b) @safe @nogc pure nothrow { immutable ulong au = a >> 32; immutable ulong bu = b >> 32; immutable ulong al = a & ((1UL << 32) - 1); immutable ulong bl = b & ((1UL << 32) - 1); ulong t = al * bl; immutable ulong w3 = t & ((1UL << 32) - 1); ulong k = t >> 32; t = au * bl + k; k = t & ((1UL << 32) - 1); immutable ulong w1 = t >> 32; t = al * bu + k; k = t >> 32; return [au * bu + w1 + k, t << 32 + w3]; } struct Barrett { uint _m; ulong im; this(uint m) @safe @nogc pure nothrow { _m = m; im = (cast(ulong)(-1)) / m + 1; } uint umod() @safe @nogc pure nothrow { return _m; } uint mul(uint a, uint b) @safe @nogc pure nothrow { ulong z = a; z *= b; immutable ulong x = umul128(z, im)[0]; uint v = cast(uint)(z - x * _m); if (_m <= v) v += _m; return v; } } long ctPowMod(long x, long n, int m) @safe pure nothrow @nogc { if (m == 1) return 0; uint _m = cast(uint) m; ulong r = 1; ulong y = safeMod(x, m); while (n) { if (n & 1) r = (r * y) % _m; y = (y * y) % _m; n >>= 1; } return r; } bool ctIsPrime(int n) @safe pure nothrow @nogc { if (n <= 1) return false; if (n == 2 || n == 7 || n == 61) return true; if (n % 2 == 0) return false; long d = n - 1; while (d % 2 == 0) d /= 2; foreach (a; [2, 7, 61]) { long t = d; long y = ctPowMod(a, t, n); while (t != n - 1 && y != 1 && y != n - 1) { y = y * y % n; t <<= 1; } if (y != n - 1 && t % 2 == 0) { return false; } } return true; } enum bool isPrime(int n) = ctIsPrime(n); Tuple!(long, long) invGcd(long a, long b) @safe pure nothrow @nogc { a = safeMod(a, b); if (a == 0) return Tuple!(long, long)(b, 0); long s = b, t = a, m0 = 0, m1 = 1; while (t) { immutable long u = s / t; s -= t * u; m0 -= m1 * u; long tmp = s; s = t; t = tmp; tmp = m0; m0 = m1; m1 = tmp; } if (m0 < 0) m0 += b / s; return Tuple!(long, long)(s, m0); } int ctPrimitiveRoot(int m) @safe pure nothrow @nogc { if (m == 2) return 1; if (m == 167_772_161) return 3; if (m == 469_762_049) return 3; if (m == 754_974_721) return 11; if (m == 998_244_353) return 3; int[20] divs; divs[0] = 2; int cnt = 1; int x = (m - 1) / 2; while (x % 2 == 0) x /= 2; for (int i = 3; (cast(long) i) * i <= x; i += 2) if (x % i == 0) { divs[cnt++] = i; while (x % i == 0) x /= i; } if (x > 1) divs[cnt++] = x; for (int g = 2;; g++) { bool ok = true; foreach (i; 0 .. cnt) if (ctPowMod(g, (m - 1) / divs[i], m) == 1) { ok = false; break; } if (ok) return g; } } enum primitiveRoot(int m) = ctPrimitiveRoot(m); struct StaticModInt(int m) if (1 <= m) { import std.traits : isSigned, isUnsigned, isSomeChar; alias mint = StaticModInt; public: static int mod() { return m; } static mint raw(int v) { mint x; x._v = v; return x; } this(T)(T v) if (isSigned!T) { long x = cast(long)(v % cast(long)(umod())); if (x < 0) x += umod(); _v = cast(uint)(x); } this(T)(T v) if (isUnsigned!T || isSomeChar!T) { _v = cast(uint)(v % umod()); } this(bool v) { _v = cast(uint)(v) % umod(); } auto opAssign(T)(T v) if (isSigned!T || isUnsigned!T || isSomeChar!T || is(T == bool)) { return this = mint(v); } inout uint val() pure { return _v; } ref mint opUnary(string op)() pure nothrow @safe if (op == "++") { _v++; if (_v == umod()) _v = 0; return this; } ref mint opUnary(string op)() pure nothrow @safe if (op == "--") { if (_v == 0) _v = umod(); _v--; return this; } mint opUnary(string op)() if (op == "+" || op == "-") { mint x; return mixin("x " ~ op ~ " this"); } ref mint opOpAssign(string op, T)(T value) if (!is(T == mint)) { mint y = value; return opOpAssign!(op)(y); } ref mint opOpAssign(string op, T)(T value) if (op == "+" && is(T == mint)) { _v += value._v; if (_v >= umod()) _v -= umod(); return this; } ref mint opOpAssign(string op, T)(T value) if (op == "-" && is(T == mint)) { _v -= value._v; if (_v >= umod()) _v += umod(); return this; } ref mint opOpAssign(string op, T)(T value) if (op == "*" && is(T == mint)) { ulong z = _v; z *= value._v; _v = cast(uint)(z % umod()); return this; } ref mint opOpAssign(string op, T)(T value) if (op == "/" && is(T == mint)) { return this = this * value.inv(); } ref mint opOpAssign(string op, T)(T value) if (op == "^^" && (is(T == int) || is(T == long))) { return this = this.pow(value); } mint pow(long n) const pure { assert(0 <= n); mint x = this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } mint inv() const pure { static if (prime) { assert(_v); return pow(umod() - 2); } else { auto eg = invGcd(_v, mod()); assert(eg[0] == 1); return mint(eg[1]); } } mint opBinary(string op, R)(const R value) const pure if (op == "+" || op == "-" || op == "*" || op == "/") { static if (is(R == mint)) { mint x; x += this; return x.opOpAssign!(op)(value); } else { mint x; x += this; mint y = value; return x.opOpAssign!(op)(y); } } mint opBinary(string op, R)(const R value) const pure if (op == "^^") { return pow(value); } mint opBinaryRight(string op, L)(const L value) const if (!is(L == mint)) { mint y = value; return y.opBinary!(op)(this); } bool opEquals(R)(const R value) const { static if (is(R == mint)) { return _v == value._v; } else { mint y = mint(value); return this == y; } } private: uint _v; uint umod() pure const { return m; } enum bool prime = isPrime!(m); } struct DynamicModInt(int id) { import std.traits : isSigned, isUnsigned, isSomeChar; alias mint = DynamicModInt; public: static int mod() { return bt.umod(); } static void setMod(int m) { assert(1 <= m); bt = Barrett(m); } static mint raw(int v) { mint x; x._v = v; return x; } this(T)(T v) if (isSigned!T) { long x = cast(long)(v % cast(long)(umod())); if (x < 0) x += umod(); _v = cast(uint)(x); } this(T)(T v) if (isUnsigned!T || isSomeChar!T) { _v = cast(uint)(v % umod()); } this(bool v) { _v = cast(uint)(v) % umod(); } auto opAssign(T)(T v) if (isSigned!T || isUnsigned!T || isSomeChar!T || is(T == bool)) { return this = mint(v); } inout uint val() { return _v; } ref mint opUnary(string op)() nothrow @safe if (op == "++") { _v++; if (_v == umod()) _v = 0; return this; } ref mint opUnary(string op)() nothrow @safe if (op == "--") { if (_v == 0) _v = umod(); _v--; return this; } mint opUnary(string op)() if (op == "+" || op == "-") { mint x; return mixin("x " ~ op ~ " this"); } ref mint opOpAssign(string op, T)(T value) if (!is(T == mint)) { mint y = value; return opOpAssign!(op)(y); } ref mint opOpAssign(string op, T)(T value) if (op == "+" && is(T == mint)) { _v += value._v; if (_v >= umod()) _v -= umod(); return this; } ref mint opOpAssign(string op, T)(T value) if (op == "-" && is(T == mint)) { _v -= value._v; if (_v >= umod()) _v += umod(); return this; } ref mint opOpAssign(string op, T)(T value) if (op == "*" && is(T == mint)) { _v = bt.mul(_v, value._v); return this; } ref mint opOpAssign(string op, T)(T value) if (op == "/" && is(T == mint)) { return this = this * value.inv(); } ref mint opOpAssign(string op, T)(T value) if (op == "^^" && (is(T == int) || is(T == long))) { return this = this.pow(value); } mint pow(long n) const { assert(0 <= n); mint x = this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; } mint inv() const { auto eg = invGcd(_v, mod()); assert(eg[0] == 1); return mint(eg[1]); } mint opBinary(string op, R)(const R value) if (op == "+" || op == "-" || op == "*" || op == "/") { static if (is(R == mint)) { mint x; x += this; return x.opOpAssign!(op)(value); } else { mint y = value; return opOpAssign!(op)(y); } } mint opBinary(string op, R)(const R value) const if (op == "^^") { return pow(value); } mint opBinaryRight(string op, L)(const L value) const if (!is(L == mint)) { mint y = value; return y.opBinary!(op)(this); } bool opEquals(R)(const R value) const { static if (is(R == mint)) { return _v == value._v; } else { mint y = mint(value); return this == y; } } private: uint _v; static Barrett bt = Barrett(998_244_353); uint umod() { return bt.umod(); } } alias modint998244353 = StaticModInt!(998244353); alias modint1000000007 = StaticModInt!(1000000007); alias modint = DynamicModInt!(-1); alias mint = modint998244353; void main() { int N, X, Q; cin(N, X, Q); auto dsu = new PotentialUnionFind!(int, "a^b", "0", "a")(N); auto B = new long[][][](N, 30, 2); foreach (ref v; B) { foreach (ref vv; v) { vv[0] = 1; } } foreach (_; 0 .. Q) { int k; cin(k); if (k == 1) { int u, w; cin(u, w); int a = dsu.leader(u); int b = dsu.leader(X); int c = dsu.merge(u, X, w); w = dsu.diff(a, b); if (a != c) swap(a, b); foreach (d; 0 .. 30) { B[a][d][0] += B[b][d][w >> d & 1]; B[a][d][1] += B[b][d][1 - (w >> d & 1)]; } } else if (k == 2) { int u, v; cin(u, v); if (dsu.same(u, v)) { int d = dsu.diff(u, v); d.writeln; X += d; X %= N; } else { (-1).writeln; } } else if (k == 3) { int v; cin(v); v = dsu.leader(v); mint ans = 0; foreach (d; 0 .. 30) { ans += (mint(2) ^^ d) * B[v][d][0] * B[v][d][1]; } ans.val.writeln; } else if (k == 4) { int v; cin(v); X += v; X %= N; } } }