/** * * * * */ voidshow(string s, int *a, int l, int r){ cout << s; for (int i = l; i <= r; i++) { cout << a[i] << " "; } cout << endl; }
// 置换单位元, n是置换的长度 voidget_one(int *a, int n){ for (int i = 0; i < n; ++i) { a[i] = i; } }
// 拷贝置换 voidcpy(int *src, int *dst, int n){ for (int i = 0; i < n; i++) { dst[i] = src[i]; } }
// 置换标准化, c=(_b^a) voidnormal(int *a, int *b, int *c, int n){ vector<int> res(n); for (int i = 0; i < n; i++) { res[a[i]] = b[i]; } cpy(res.data(), c, n); }
// 置换乘法 c=a*b voidmul(int *a, int *b, int *c, int n){ vector<int> res(n); for (int i = 0; i < n; ++i) { res[i] = b[a[i]]; } cpy(res.data(), c, n); }
// 分解置换为循环乘积 vvi decomposition(int *a, int n){ vector<bool> vis(n); vvi res; for (int i = 0; i < n; ++i) { vector<int> tem; if (vis[a[i]]) { continue; } int now = i; while (!vis[a[now]]) { vis[a[now]] = true; tem.push_back(a[now]); now = a[now]; }
res.push_back(tem); } return res; }
// 合并循环乘积为置换 voidcomposition(vvi &a, int *b, int n){ vector<int> res(n + 1); for (auto &x:a) { for (int i = 0; i < x.size(); i++) { res[x[i]] = x[(i + 1) % x.size()]; } } cpy(res.data(), b, n); }
// 分解转换为一个循环乘积, 保证只能分出一个 // a->b voiddecomposition(int *a, int *b, int n){ cpy(decomposition(a, n).front().data(), b, n); }
// 合并一个循环乘积为置换 voidcomposition(int *a, int *b, int n){ vector<int> res(n); for (int i = 0; i < n; i++) { res[a[i]] = a[(i + 1) % n]; } cpy(res.data(), b, n); }
// 置换快速幂 b=a^k voidqpow(int *a, int n, int k, int *b){ vvi tem = decomposition(a, n); for (auto &x:tem) { for (int i = 0; i < x.size(); i++) { b[x[i]] = x[(i + k) % x.size()]; } } }
voidinv(int *a, int *b, int n){ vector<int> res(n); for (int i = 0; i < n; i++) { res[a[i]] = i; } cpy(res.data(), b, n); }
// 置换开方 b = a^{1/n} boolsqrt(int *a, int *b, int n, int k){ vector<int> base(n), basepow(n); vvi fac = decomposition(a, n); for (vi &faci:fac) { int size = faci.size(); if (__gcd(k, size) != 1) { // 这个算法找不到解,但是解应该是存在的 returnfalse; } for (int i = 0; i < size; i++) { base[i] = (i + 1) % size; } qpow(base.data(), size, k, basepow.data());
bit(int mx) { x2 = 1; while (x2 < mx) x2 <<= 1; d = vi(x2 + 1); }
voidadd(int i, int x = 1){ for (i++; i <= x2; i += i & -i) d[i] += x; }
intkth(int k){ if (k > d[x2]) return-1; int i = x2 >> 1, p = 0; while (i) { if (d[p + i] < k) p += i, k -= d[p]; i >>= 1; } return p; } };
// a[1...n] voidgetCircle(int *a, int n, int k){ static bit b(N); for (int i = 1; i <= n; i++) { b.add(i, 1); } for (int i = 1, rk = 1; i <= n; i++) { int mod = n - i + 1; int add = (k - 1 + mod) % mod;