题解:P17206 「DLESS-6」Lost Requiem
\(n\) 是质数,所以 \(a_{(xi+y)\bmod{n}}\) 是 \(a\) 的一个置换。这 \(n(n-1)\) 种置换构成一个群,而满足条件的 \(a\) 相当于是所在轨道中字典序最小的序列,因此题目转化为求轨道个数。
设 \(g(x,y)\) 为对应置换的不动点个数,由 Burnside 引理,所求即为
设满足 \(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\)。
综上,答案为
对 \(n-1\) 做质因数分解,DFS 枚举约数的同时维护 \(\varphi\) 的值即可。时间复杂度为 \(\mathcal{O}(\sqrt{n}+\tau(n-1)\log{n})\)。
主要代码
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;
}

浙公网安备 33010602011771号