http://codeforces.com/gym/101955/problem/C
题目大意:给一个只排前
k
k
k项的排序算法,问一个以
1
−
n
1-n
1−n为元素的数组有多少种排列方式能在这个排序算法完成之后能使最长上升子序列的长度达到
n
−
1
n-1
n−1。
思路:(1)
k
>
=
n
k>=n
k>=n时的答案为
n
!
n!
n!;(2)当
k
<
n
k<n
k<n时:如果前
k
k
k个元素是
1
−
k
1-k
1−k,那么后面的
n
−
k
n-k
n−k个数要么保持有序要么可以把任意一个数放到另外一个数的位置上,贡献为
(
1
+
(
n
−
k
)
∗
(
n
−
k
−
1
)
)
∗
k
!
(1+(n-k)*(n-k-1))*k!
(1+(n−k)∗(n−k−1))∗k!;如果前
k
k
k个元素不是
1
−
k
1-k
1−k,想要满足题意也只能是从后面的
n
−
k
n-k
n−k个数中挑一个数插到前
k
k
k个位置的某一位置上,贡献为
(
n
−
k
)
∗
k
∗
k
!
(n-k)*k*k!
(n−k)∗k∗k!。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
using namespace std;
typedef long long ll;
int t;
ll n,k,q;
int main()
{
int times=0;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld",&n,&k,&q);
if(k>n)
k=n;
ll ans=1;
for(int i=2;i<=k;i++)
ans=ans*i%q;
ans=ans*(1+(n-k)*(n-k-1)+(n-k)*k)%q;
printf("Case #%d: %lld\n",++times,ans);
}
return 0;
}