题意:问长度为n的所以排列中,在前k个数排好序的情况下,最长上升子序列大于等于n-1的排列数,对p取模
主要分这么几种情况
1,前k个排完序整个数组有序,最长上升子序列为n,有种情况(前k个任意,后面n-k个有序)
2,前k个排完序,前面贡献k个上升,后面n-k个贡献n-k-1种上升,有
种情况,(前k个任意,后n-k个LIS等于n-k-1)
3,蒋val等于k+1拿到前k个,替换一个数拿到后n-k个,例如下面这种情况
这里前面排好序是124,后面56保持有序,即满足LIS大于等于n-1,4在前面可以随意放,3在后面可以随意放,有
种情况
4,蒋val大于等于k+2的数放到前面,替换的数放到后面
可以看到,后面n-k个数必须保持有序,而替换的数有种选法
有
讲以上所有答案累加,得出答案为
需要注意当n小于k时,也就是整个数组排序,可以随便摆,有种
代码如下
#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair<int,int>
#define et cout<<'\n'
#define xx first
#define yy second
#define ld long double
using namespace std;
const int N = 1e6+10;
template <typename _Tp>void input(_Tp &x){
char ch(getchar());bool f(false);while(!isdigit(ch))f|=ch==45,ch=getchar();
x=ch&15,ch=getchar();while(isdigit(ch))x=x*10+(ch&15),ch=getchar();
if(f)x=-x;
}
template <typename _Tp,typename... Args>void input(_Tp &t,Args &...args){input(t);input(args...);}
signed main(){
int T;
cin>>T;
fer(i,1,T){
int n,k,q;
cin>>n>>k>>q;
int ans =1;
if(n<k){
fer(i,1,n){
ans*=i;
ans%=q;
}
cout<<"Case #"<<i<<": "<<ans<<'\n';
continue;
}
else{
int fak=1;
fer(i,1,k){
fak*=i;
fak%=q;
}
int tmp=n;
tmp=(tmp-k+q)%q;
int tmp2=(n-1+q)%q;
tmp*=tmp2;
tmp%=q;
tmp+=1;
tmp%=q;
ans=(fak*tmp)%q;
cout<<"Case #"<<i<<": "<<ans<<'\n';
}
}
}