题解:P17394 [ICPC 2018 Shenyang R] Insertion Sort

· · 题解

神秘原题大赛 T1,赛时瞪眼找的规律,现在证明一下。

一个排列的最长上升子序列长度至少为 (n-1),相当于从 1,2,3,\dots,n 中选出至多一个数插到别的位置,其他数相对位置不变所构成的排列。下文中,我们称这个数为错位数。

考虑固定 k,计算 n 变化带来的贡献。

综上所述,每次我们求一遍阶乘,递推记录上一个答案与偏移量即可,时间复杂度 O(Tn)。代码如下,可供参考:

#include<bits/stdc++.h>
using namespace std;
int T,n,k,q,fac;
int main(){
    cin>>T;
    for(int t=1;t<=T;t++){
        cin>>n>>k>>q;
        k=min(n,k),fac=1;
        for(int i=1;i<=k;i++)fac=1ll*fac*i%q;
        int ans=fac,del=1ll*fac*k%q;
        for(int i=k+1;i<=n;i++)ans=(ans+del)%q,del=(del+2*fac%q)%q;
        cout<<"Case #"<<t<<": "<<ans<<'\n';
    }
    return 0;
}