簡單的計數題,題意是讓你對一個1到n的一個排列執行k次插入排序,排完序以後要滿足最長上升遞增子序列的長度至少爲n-1,問這樣的排列由多少種。做的時候是這樣做的,首先考慮前k個正好是前k個,然後後面的最長上升子序列大於等於n-k-1的排列的個數有多少,剛開始手推,發現推出來的公式是錯誤的,然後這個就打了一下表,之後考慮前面的k個有一個不屬於1到k的範圍以內,在紙上畫了一下,發現第k個值比較特殊,多了n-k-1種,其他的都是一樣就把第k+1個值插入放到前面,然後前面這個數插入到後面的空位中就行了。
代碼:
#include<bits/stdc++.h>
using namespace std;
int data[1000] = {1, 1, 2, 5, 10, 17, 26, 37, 50, 65, 82, 101, 122, 145, 170,
197, 226, 257, 290, 325, 362, 401, 442, 485, 530, 577, 626, 677, 730, 785, 842,
901, 962, 1025, 1090, 1157, 1226, 1297, 1370, 1445, 1522, 1601,
1682, 1765, 1850, 1937, 2026, 2117, 2210, 2305, 2402, 2501,
};
using ll=long long ;
int main()
{
int t;
while(scanf("%d",&t)!=EOF)
{
int x=1;
ll n,k,q;
while(t--)
{
scanf("%lld%lld%lld",&n,&k,&q);
k=min(n,k);
if(k==1)
{
printf("Case #%d: %I64d\n",x++,data[n]%q);
}
else if(k==n)
{
ll ans=1;
for(ll i=1; i<=n; i++)
ans=ans*i%q;
printf("Case #%d: %I64d\n",x++,ans);
}
else
{
ll ans=1;
for(int i=1; i<=k; i++)
{
ans=ans*i%q;
}
ans = ans*(data[n-k] + k*(n-k)+n-k-1)%q;
printf("Case #%d: %I64d\n",x++,ans);
}
}
}
}