题解:P17206 「DLESS-6」Lost Requiem

· · 题解

设 $g(x,y)$ 为对应置换的不动点个数,由 Burnside 引理,所求即为 $$ \dfrac{1}{n(n-1)}\sum_{x=1}^{n-1}\sum_{y=0}^{n-1}g(x,y) $$ 设满足 $p_i=(xi+y)\bmod{n}$ 的排列 $p$ 有 $c(x,y)$ 个置换环,同一个置换环内必须填同一种数,于是 $g(x,y)=m^{c(x,y)}$。 考虑如何求出 $c(x,y)$。 若 $x=1,y=0$,则 $c(x,y)=n$。 若 $x=1,y\neq 0$,设从 $i$ 出发走 $k$ 步会回到 $i$,则 $ky\equiv 0\pmod{n}$,显然满足条件的最小正整数为 $k=n$,因此 $c(x,y)=1$。 若 $x\neq 1$,考虑 $t\equiv xt+y\pmod{n}$ 有唯一解。对于任意的 $i$,将其表示成 $i=t+j$,则 $x(t+j)+y\equiv t+xj\pmod{n}$,因此该置换实际上和 $y=0$ 对应的置换同构。对于 $i=0$,显然 $xi=0$,这会贡献一个置换环;对于 $i\neq 0$,还是设从 $i$ 出发走 $k$ 步会回到 $i$,则 $x^k\equiv 1\pmod{n}$,因此环长为 $\operatorname{ord}_n(x)$。加起来得到 $c(x,y)=1+\dfrac{n-1}{\operatorname{ord}_n(x)}$。根据经典结论,对于任意的 $d\mid(n-1)$,恰好有 $\varphi(d)$ 个元素的阶为 $d$。 综上,答案为 $$ \dfrac{1}{n(n-1)}\left(m^n+(n-1)m+n\sum_{\substack{d\mid(n-1)\\d>1}}\varphi(d)m^{1+\frac{n-1}{d}}\right) $$ 对 $n-1$ 做质因数分解,DFS 枚举约数的同时维护 $\varphi$ 的值即可。时间复杂度为 $\mathcal{O}(\sqrt{n}+\tau(n-1)\log{n})$。 :::success[主要代码] ```cpp int tc, p, n, m; vector<pii> vec; mint sum; mint qpow(mint a, ll b) { mint res = 1; for (; b; b >>= 1) { if (b & 1) res *= a; a *= a; } return res; } void fac(int n) { vec.clear(); for (int d = 2; (ll)d * d <= n; ++d) { if (n % d) continue; int cnt = 0; while (n % d == 0) { n /= d; ++cnt; } vec.emplace_back(d, cnt); } if (n > 1) vec.emplace_back(n, 1); } void dfs(int x, int d, int phi) { if (x == vec.size()) { if (d != 1) sum += phi * qpow(m, (n - 1) / d + 1); return; } auto [pr, cnt] = vec[x]; int pw = 1, ph = 1; for (int i = 0; i <= cnt; ++i) { dfs(x + 1, d * pw, phi * ph); if (i == cnt) break; pw *= pr; ph = !i ? pr - 1 : ph * pr; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> tc >> p; mint::setMod(p); while (tc--) { cin >> n >> m; fac(n - 1); sum = 0; dfs(0, 1, 1); cout << (qpow(m, n) + mint(n - 1) * m + n * sum) / (mint(n) * (n - 1)) << '\n'; } return 0; } ``` :::