正题
题目大意
对于n个数组成的序列,求排好序需要最少交换次数的期望次数。
解题思路
我们可以先求出需要次数总和在乘上n!n!n!的逆元
先打一个表,不难发现
f(n)=f(n−1)∗n+(n−1)(n−1)!f(n)=f(n-1)*n+(n-1)(n-1)!f(n)=f(n−1)∗n+(n−1)(n−1)!
然后我们在考虑插入,对于前面一个序列,我们可以插入一个比前面的数都大的数进去,之后我们会发现只有插在最后面才不会增加交换次数,其他都会增加一次交换次数,式子显然正确。
之后fff离线预处理,逆元在线处理
时间复杂度:O(N+Tlogp)O(N+T\ \ log\ p)O(N+T log p)
code
#include<cstdio>
#include<cctype>
#define p 998244353
#define N 10000000
#define ll long long
using namespace std;
ll t,f[N+10],k,n,jx[N+10];
ll read() {int x=0,f=1; char c=getchar();while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();return x*f;
}
void write(ll x){if (x>9) write(x/10); putchar(x%10+48); return;
}
ll power(ll x,ll b)//费马小求逆元
{ll ans=1;while(b){if(b&1) ans=ans*x%p;x=x*x%p;b>>=1;}return ans;
}
int main()
{scanf("%lld",&t);f[2]=1;jx[2]=2;for(ll i=3;i<=N;i++)//预处理{jx[i]=jx[i-1]*i%p;//阶乘预处理f[i]=(f[i-1]*i%p+(jx[i]-jx[i-1]+p)%p)%p;}for(ll i=1;i<=t;i++){n=read();write(power(jx[n],p-2)*f[n]%p);putchar('\n');}
}