根據打表可得,對於n的情況
任意一個首位!=1的排列時,則其答案-1可以與首位為1的情況對應
當n=4時
排列 答案
1 2 3 4 ------ 0
1 2 4 3 ------ 1
1 3 2 4 ------ 1
1 3 4 2 ------ 2
1 4 2 3 ------ 2
1 4 3 2 ------ 1
2 1 3 4 ------ 1
2 1 4 3 ------ 2
2 3 1 4 ------ 2
2 3 4 1 ------ 3
2 4 1 3 ------ 3
2 4 3 1 ------ 2
3 1 2 4 ------ 2
3 1 4 2 ------ 3
3 2 1 4 ------ 1
3 2 4 1 ------ 2
3 4 1 2 ------ 2
3 4 2 1 ------ 3
4 1 2 3 ------ 3
4 1 3 2 ------ 2
4 2 1 3 ------ 2
4 2 3 1 ------ 1
4 3 1 2 ------ 3
4 3 2 1 ------ 2
記f[i]表示i個數,所有i個數可以組成的排列的答案總和
則我們發現,有(n-1)(n-1)!項首位不等於1的排列,對答案有1的貢獻
除此之外,我們會發現,首項為1的數由於有n個數(包括自己)與其對應
所以對答案有nf[i-1]的貢獻
所以f[i]=if[i-1]+(i-1)(i-1)!
注意要逆元
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mo 998244353ll
ll t,f[10000010],n,jc[10000010];
ll qp(ll x,ll y){
ll r=1;
x%=mo;
while(y){
if(y&1)r=r*x%mo;
y>>=1;
x=(x*x)%mo;
}
return r;
}
int main(){
freopen("inverse.in","r",stdin);
freopen("inverse.out","w",stdout);
jc[0]=1;
for(ll i=1;i<=10000010;i++)
jc[i]=jc[i-1ll]*i%mo;
for(ll i=1;i<=10000010;i++)
f[i]=(i*f[i-1ll]%mo+(i-1ll)*jc[i-1ll]%mo)%mo;
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
printf("%lld\n",f[n]*qp(jc[n],mo-2ll)%mo);
}
}