题意:
Bubble sort is a simple sorting algorithm that repeatedly steps through the list to be sorted, compares each pair of adjacent items and swaps them if they are in the wrong order. The pass through the list is repeated until no swaps are needed, which indicates that the list is sorted.
Izdihar is an ACM-ICPC master and provides a pseudocode implementation about the bubble sort for you. The algorithm for a list of sortable items A can be expressed as (1-based array):
- n = length(A)
- repeat
- swapped = false
- for i = 2 to n inclusive do
- if A[i-1] > A[i] then
- swap( A[i-1], A[i] )
- swapped = true
- if A[i-1] > A[i] then
She says a permutation of $$$1$$$ to $$$n$$$ is almost sorted if the length of its longest increasing subsequence is at least $$$n-1$$$.
You are asked to count the number of permutations of $$$1$$$ to $$$n$$$ which, after $$$k$$$ times passing through the list in the bubble sort, would become an almost sorted permutation.
问k次后一个1到n的序列的所有全排列有多少被排好序了,称一个序列排好序,是这个序列的LIS>=n-1。
这个题很难,gym上这题毛子那边出了三个队,中国出了一个队,但是代码短小精悍。
一个易证的事实:冒泡k次后一个序列的后k个数一定排好序了,对于冒泡k次后的新序列,第i位的数一定是原序列前min(i+k,n)个未在原序列中前i-1位出现的数,意味着新序列第i个数在原序列有k+1种位置。
一个序列的LIS>=n-1相当于将一个序列的某个区间想左或右循环移动。
那么我们就可以计数了:我们枚举新序列的每个数在原序列的位置。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int T,n,k,mod;
LL bit[55];
int main()
{
scanf("%d",&T);
for (int z=1;z<=T;++z)
{
scanf("%d%d%d",&n,&k,&mod);
printf("Case #%d: ",z);
if (k>=n)
{
LL ans=1;
for (int i=1;i<=n;++i) ans=ans*i%mod;
printf("%lld\n",ans);
continue;
}
bit[0]=1;
for (int i=1;i<=n;++i) bit[i]=1LL*bit[i-1]*(k+1)%mod;
LL ans=0;
//sorted
ans=bit[n-k];
//left shift
for (int len=2;len<=n-k;++len)
ans+=1LL*(n-k-len+1)*bit[n-k-1]%mod,ans%=mod;
//right shift
for (int len=3;len<=n-k;++len)
ans+=1LL*(n-k-len+1)*bit[n-k-len+1]%mod,ans%=mod;
//last k
for (int i=1;i<=k;++i) ans=ans*i%mod;
printf("%lld\n",ans);
}
return 0;
}