多組詢問
分解法
考慮,感覺上直接算答案不好算,所以考慮算長度爲的所有排列改變的次數的排列的個數算出來
之後再把個數乘以次數的平方即可
設表示長度爲的排列的改變次數爲的排列個數
考慮把最大的插入到長度爲的改變次數爲的排列中,則有個空可以插,其中最前面的空插進去會使改變次數加一,所以有個空使改變次數不變
考慮插在最前面則原改變次數應爲
所以
其實就是第一類斯特林數的遞推公式
提前預處理一下即可做到
分解法
仍然是,原來的是把問題拆開,好做但是不能直接算
不妨大膽一點,設表示長度爲的答案
仍然考慮從轉移過來
還是上面那句
考慮把最大的插入到長度爲的改變次數爲的排列中,則有個空可以插,其中最前面的空插進去會使改變次數加一,所以有個空使改變次數不變
考慮插在最前面,原本的改變次數爲的都變爲了
也就是
我們設表示原本算貢獻時是按照來算的長度爲的答案
對於那個,因爲插在最前面後面的個數共有種組合
所以
同樣這麼推
/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年09月28日 星期六 09時34分38秒
*******************************/
#include <cstdio>
#include <fstream>
using namespace std;
const int maxn = 100005;
const int mod = 998244353;
//{{{cin
struct IO{
template<typename T>
IO & operator>>(T&res){
res=0;
bool flag=false;
char ch;
while((ch=getchar())>'9'||ch<'0') flag|=ch=='-';
while(ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
if (flag) res=~res+1;
return *this;
}
}cin;
//}}}
int T,n;
int f[maxn],g[maxn],fac[maxn];
int main()
{
fac[0]=1;
for (int i=1;i<=100000;++i){
fac[i]=1ll*fac[i-1]*i%mod;
f[i]=((1ll*f[i-1]*i%mod+2ll*g[i-1]%mod)%mod+fac[i-1])%mod;
g[i]=(1ll*g[i-1]*i%mod+fac[i-1])%mod;
}
cin>>T;
while (T--){
cin>>n;
printf("%d\n",f[n]);
}
return 0;
}
如有哪裏講得不是很明白或是有錯誤,歡迎指正
如您喜歡的話不妨點個贊收藏一下吧