[CF1091D]New Year and the Permutation Concatenation
題目大意
給$n!$個$n$的排列,按字典序從小到大連成一條序列,例如$3$的情況為:$[1,2,3, 1,3,2, 2,1,3 ,2,3,1 ,3,1,2 ,3,2,1]$,問其中長度為$n$,且和為$sum=n\times (n+1)/2$的序列有多少個?
試題分析
對於合理的序列有兩種情況,第一種是就是排列的,第二種就是前面$k$個與後面的$n-k$的一塊組成。
對於第一種情況,答案只要$n$個,所以我們只考慮第二種情況。
當$n=3$時,$n\times n!=3!\times 3\text{=}18$
而直接生成的序列為$[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]$
而我們思考$next\_permutatin$是怎麼判斷下一個排列的,假設某一個序列長度為$n$,最長的遞減的字尾長度$k$,那麼它的下一個排列是這樣產生的:選取序列第$n-k$個數,與後$k$個數中最小的那個交換(其實就是最後一個),然後將後$k$個數按從小到大排序。
如圖所示,若想要成為第二種情況,則$A$集合需等於$A’$集合。
而這時我們能確定$A$當前的一定不是遞減的,所以問題可以轉換成排除法當前序列末尾$k$個是按序遞減的情況數。
舉個例子:
$k=1$時,排除$[3,1,3],[2,2,1],[3,2,3],[1,3,1].[2,3,2]$
$k=2$時,排除$[(3,2),2],[(3,1),3]$
所以說我們現在只要求不行的方案數即可。
只要確定了前$k-x$個數,那麼後面關於$x$的遞減順序是一定的。
所以當k=x時,排除方案數為$A_n^k$,但是最後一個是沒有連線的,所以要-1,即為$A_n^k-1$
所以總方案數為$n\times n!-(n-1) - \sum_{k=1}^{n-1} (\frac{n!}{k!}-1)$.
整理的$n\times n!-\sum_{k=1}^{n-1} \frac{n!}{k!}$
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define int long long #define mod 998244353 using namespace std; inline int read() { int f=1,ans=0;char c; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return ans*f; } const int N=2000001; int ans,n,fac[N],f[N]; signed main(){ n=read();fac[0]=1; for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i,fac[i]%=mod; f[n]=1; for(int i=n-1;i>=1;i--) f[i]=f[i+1]*(i+1),f[i]%=mod; ans=n*fac[n]; for(int i=1;i<n;i++) ans=((ans-f[i])%mod+mod)%mod; printf("%d\n",ans); }View Code