A
时间限制:5000MS内存限制:256000KB
题目描述
HJW发明了一种神奇的排序方法。有了这个方法,对于任意数列,排序的复杂度为把该序列变从小到大排序最少交换的次数。询问对于n的任意一个排列,排序的复杂度期望。
输入
从文件 inverse.in 中读入数据。
输入第一行包含一个正整数 T ,表示数据组数。
对于每组数据,第一行有一个正整数n。
输出
输出到文件 inverse.out 中。
输出共 T 行,每行一个整数。
对于每组数据,输出一个整数,表示答案对 998244353 取模的结果。
输入样例复制
2
2
3
输出样例复制
499122177
166374060
当n=2,排列为{1,2}和{2,1},交换次数为0和1,期望为1/2。
当n=3,排列为{1,2,3},{1,3,2},{2,1,3},{2,3,1},{3,1,2},{3,2,1},交换次数为0,1,1,2,2,1,期望为7/6。
说明
对于20%的数据,T<=10,n<=10; 对于另外20%的数据,T=1; 对于另外10%的数据,n<=10^3; 对于100%的数据,T<=10^5,n<=10^7。
题解: 推导最小交换次数:将数字与最终所处位置的下标连线,得到k个环,则最小交换次数为n-k
如 6 4 2 1 3 5 3 4 2 1 5 6
1-4-2-3-5-6-1 最小交换 6-1=5 1-4-2-3-1 5-5 6-6 最小交换6-3=3
设f[n]为n个数的期望环数量,对于f[n-1]已知,第n个数有n个空隙可以插入,且只有插入队尾可以得到一个新的环
所以f[n]=f[n-1]+1/n;
答案为n-sigma(1-n,1/i)
1/i即i的逆元,根据费马小定理,在模意义下i的逆元为i^(p-2)
因为快速幂复杂度为根号n,所以问题转化为线性求逆元
线性求逆元公式: a[i]:=(p-(p div i))*a[p mod i]mod p a[1]=1
const
maxn=10000000;
p=998244353;
var
a,sum:array[1..maxn]of int64;
n,i,t:longint;
procedure init;
var
i:longint;
begin
a[1]:=1;
for i:=2 to maxn do
a[i]:=(p-(p div i))*a[p mod i]mod p;
sum[1]:=a[1];
for i:=2 to maxn do
sum[i]:=(sum[i-1]+a[i])mod p;
end;
begin
init;
readln(t);
for i:=1 to t do
begin
readln(n);
writeln((n-sum[n]+p)mod p);
end;
end.