結果
| 問題 |
No.2428 Returning Shuffle
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2023-08-19 05:07:35 |
| 言語 | D (dmd 2.109.1) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,619 bytes |
| コンパイル時間 | 6,718 ms |
| コンパイル使用メモリ | 212,600 KB |
| 実行使用メモリ | 80,948 KB |
| 最終ジャッジ日時 | 2024-11-28 18:45:22 |
| 合計ジャッジ時間 | 11,969 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 18 WA * 5 |
ソースコード
import std;
void main () {
int N, M; readln.read(N, M);
int[] T = new int[](M);
int[][] S = new int[][](M, 0);
foreach (i; 0..M) {
auto input = readln.split.to!(int[]);
T[i] = input[0];
S[i] = input[1..$];
S[i][] -= 1; // 0-indexed
}
solve(N, M, T, S);
}
void solve (int N, int M, int[] T, int[][] S) {
// 巡回置換の定義より、「元と変わった分」だけのループが必要なはず
// (最後に「元と変わっている」ということは、累積した巡回置換を一つにまとめたときに、要素数=(変わった数)の置換になるはず)
// あくまで予想。未証明。
// というわけで、一回シミュレートしてカウントする。
// 巡回置換の定義でのたうちまわってたけど、ようやくシミュレートできた。でもどうにもちがうっぽいな
// 見えた。「巡回」の連結成分みたいなものがあって、これのLCMをとればいいっていうことだろう
// また、各連結成分を見つけるのは比較的速いはず
struct pair {
int idx;
int val;
}
DList!pair Q;
int[] arr = new int[](N);
foreach (i; 0..N) {
arr[i] = i;
}
foreach (i; 0..M) {
if (S[i].length == 2) {
swap(arr[ S[i][0] ], arr[ S[i][1] ]);
} else {
foreach (j; 0..S[i].length) {
Q.insertBack(pair(S[i][ (j+1)%$ ], arr[ S[i][j] ]));
}
while (!Q.empty) {
auto head = Q.front; Q.removeFront;
arr[head.idx] = head.val;
}
}
}
int[] idx = new int[](N);
foreach (i, a; arr) {
idx[a] = cast(int) i;
}
// 連結成分のサイズを求める。
bool[] visited = new bool[](N);
int[] size;
foreach (i; 0..N) {
if (!visited[i]) {
int res = 0;
int begin = i;
while (true) {
if (visited[begin]) {
break;
}
begin = idx[begin];
visited[arr[begin]] = true;
res++;
}
size ~= res;
}
}
// test
// writeln(size);
const long MOD = 998244353;
// lcmの計算
long ans = size[0];
foreach (s; size[1..$]) {
long div = modInv(gcd(ans, s), MOD);
ans *= s; ans %= MOD;
ans *= div; ans %= MOD;
}
writeln(ans);
}
void read(T...)(string S, ref T args) {
auto buf = S.split;
foreach (i, ref arg; args) {
arg = buf[i].to!(typeof(arg));
}
}
long gcd (long x, long y) {
long a = max(x, y);
long b = min(x, y);
while (b != 0) {
long tmp = b;
b = a % b;
a = tmp;
}
return a;
}
long modPow (long a, long x, const int MOD) {
// assertion
assert(0 <= x);
assert(1 <= MOD);
// normalize
a %= MOD; a += MOD; a %= MOD;
// simple case
if (MOD == 1) {
return 0L;
}
if (x == 0) {
return 1L;
}
if (x == 1) {
return a;
}
// calculate
long res = 1L;
long base = a % MOD;
while (x != 0) {
if ((x&1) != 0) {
res *= base;
res %= MOD;
}
base = base*base; base %= MOD;
x >>= 1;
}
return res;
}
long modInv (long x, const int MOD) {
import std.exception;
enforce(1 <= MOD, format("Line : %s, MOD must be greater than 1. Your input = %s", __LINE__, MOD));
return modPow(x, MOD-2, MOD);
}