专栏文章
题解:P13280 「CZOI-R4」午夜巡游
P13280题解参与者 7已保存评论 8
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 8 条
- 当前快照
- 1 份
- 快照标识符
- @miowobng
- 此快照首次捕获于
- 2025/12/03 02:22 3 个月前
- 此快照最后确认于
- 2025/12/03 02:22 3 个月前
前几天刚在 STAOI 传奇全黑题比赛 中大受震撼,看到这题:排列,跑置换环……
没事这是 div3 的题。
思路
我们可以先计算出最终巡游出来的 的排列有多少种,设其为 ,那么显然会剩余 种排列 。
由于考虑范围是所有排列,那么对于每个最终巡游出来的 的排列情况都是对称的。即有 种排列满足最后巡游出某个 。
因此,最终答案就是:
用等差数列求和公式化简一下,即:
所以问题就是怎么求 。
什么时候跑 次后 ?
形象一点,我们发现给一个排列中每个 建一条 的边,其实 就在顺着边在图里不停地跑,而这个图长什么样子?当然就是几个环啦! 就从点 出发,在包含 的环里一圈一圈绕,共走 步。 而最终 就说明 绕回到点 了!这说明这个环的长度是 的因子,可以整除 。
所以我们可以用枚举 的因子的方式枚举环的长度 ,并算出环长为 的时候有多少种可能。换句话说,有多少种排列满足巡游 次后 ,且前 次巡游后都满足 。
不妨找规律:
时,即 ,显然这样的排列数等于剩下的全排列数,即 种。
时,即 的同时 ,满足前者就是 个排列,满足后者又是这些情况的 ( 在除了已经确定的 之外的其他数字中选出 的概率),综上为 。
时,就是 的情况中 在除了已经确定的 之外的其他数字中选出不是 的情况数,再乘上 在除了已经确定的 之外的其他数字中选出 的概率,就是 。
类似地, 时情况数为 。
以此类推。
发现无论环长是多少,这样的排列数都是 。
不严谨的理解: 的时候是 ,一般来说这个情况数随着 增大要么减少要么增加要么不变,而发现 取值有 种情况, 即全部情况,那么我猜他就是不变。
综上,
其中 为 的正整数因子中 的数量。
再放一遍答案:
所以我们预处理阶乘,按照上述式子算就可以了。
参考代码
时间复杂度 , 为 取值上限。
CPP#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MOD = 998244353;
int T, n, m, k, jc[10000010];
signed main() {
jc[0] = 1;
for (int i = 1; i <= 10000000; i++)
jc[i] = jc[i - 1] * i % MOD;
cin >> T;
while (T--) {
cin >> n >> m >> k;
if (m == 0) cout << jc[n] * k % MOD << endl;
else {
int cnt = 0;
for (int i = 1; i * i <= m; i++) {
if (m % i != 0) continue;
if (i <= n) cnt++;
if (i != m / i && m / i <= n) cnt++;
}
int othersum = ((n + 1) * n / 2 % MOD - k + MOD) % MOD;
int ans =
k * jc[n - 1] % MOD * cnt % MOD +
othersum * jc[n - 2] % MOD * (n - cnt) % MOD;
cout << ans % MOD << endl;
}
}
return 0;
}
如果你有任何疑问或者觉得讲得不好的地方,欢迎留言!
相关推荐
评论
共 8 条评论,欢迎与作者交流。
正在加载评论...