题目大意
Yoshinow2001 \text{Yoshinow2001} Yoshinow2001 正在为他的问题生成数据。他想要生成 { 0 , … , n − 1 } \{0,…,n−1\} {0,…,n−1} 的一个随机排列,因此他使用了以下算法:
在这里,我们可以假设函数 rand ( ) m o d n \operatorname{rand}() \bmod n rand()modn 能够以等概率地在集合 { 0 , . . . , n − 1 } \{0,...,n-1\} {0,...,n−1} 中生成随机整数。
现在 Yoshinow2001 \text{Yoshinow2001} Yoshinow2001 担心这个算法不够随机。毕竟,如果要随机排列一个序列,使得 a i ≠ i a_i≠i ai=i 的元素数量的期望应该是 n − 1 n-1 n−1。所以他想询问最终答案 a n s ans ans 的数学期望是多少。
思路
期望DP。
我们设 f i f_i fi 表示 i i i 次交换后当前值在原位的概率, g i g_i gi 表示 i i i 次交换后当前值不在原位的概率。
于是乎我们容易推出以下式子:
f i = g i − 1 ⋅ 2 n 2 + f i − 1 ⋅ ( n − 1 ) 2 n 2 g i = g i − 1 ⋅ n 2 − 2 n 2 + f i − 1 ⋅ 2 n − 2 n f_i=g_{i-1}\cdot \dfrac{2}{n^2}+f_{i-1}\cdot \dfrac{(n-1)^2}{n^2}\\ \\ \qquad \\ g_i=g_{i-1}\cdot \dfrac{n^2-2}{n^2}+f_{i-1}\cdot \dfrac{2n-2}{n} fi=gi−1⋅n22+fi−1⋅n2(n−1)2gi=gi−1⋅n2n2−2+fi−1⋅n2n−2
于是乎把这个式子往上怼就可以了。(拿下)
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 998244353;
LL n, m;
struct matrix {
LL a[2][2];
matrix operator* (const matrix &x) const {
matrix ans;
ans.a[0][0] = (a[0][0] * x.a[0][0] + a[0][1] * x.a[1][0]) % mod;
ans.a[0][1] = (a[0][0] * x.a[0][1] + a[0][1] * x.a[1][1]) % mod;
ans.a[1][0] = (a[1][0] * x.a[0][0] + a[1][1] * x.a[1][0]) % mod;
ans.a[1][1] = (a[1][0] * x.a[0][1] + a[1][1] * x.a[1][1]) % mod;
return ans;
}
};
LL ksm(LL a, LL b) {
LL ans = 1;
while (b) {
if (b & 1) ans = ans * a % mod;
b >>= 1;
a = a * a % mod;
}
return ans;
}
matrix ksm(matrix a, LL b) {
matrix ans = a;
b--;
while (b) {
if (b & 1) ans = ans * a;
a = a * a;
b >>= 1;
}
return ans;
}
int main() {
int t;
cin >> t;
while (t--) {
scanf("%lld%lld", &n, &m);
n %= mod;
LL invsqrn = ksm(n * n % mod, mod - 2);
matrix aa;
aa.a[0][0] = ((n * n - 2 * n + 2) % mod * invsqrn % mod + mod) % mod;
aa.a[0][1] = (1 - aa.a[0][0] + mod)%mod;
aa.a[1][0] = 2 * invsqrn % mod;
aa.a[1][1] = (1 - aa.a[1][0] + mod) % mod;
if (m) aa = ksm(aa, m);
printf("%lld\n", aa.a[0][1] * n % mod);
}
}