沈阳区域赛-- Insertion Sort--数学

 Insertion Sort

问答问题反馈

只看题面

  •  31.94%
  •  6000ms
  •  524288K

Insertion sort is a simple sorting algorithm that builds the final sorted array one item at an iteration.

More precisely, insertion sort iterates, consuming one input element each repetition, and growing a sorted output list.At each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there.It repeats until no input elements remain.

This type of sorting is typically done in-place, by iterating up the array, growing the sorted array behind it.At each array-position, it checks the value there against the largest value in the sorted array (which happens to be next to it, in the previous array-position checked).If larger, it leaves the element in place and moves to the next.If smaller, it finds the correct position within the sorted array, shifts all the larger values up to make a space, and inserts into that correct position.

The resulting array after kk iterations has the property where the first kk entries are sorted.In each iteration the first remaining entry of the input is removed, and inserted into the result at the correct position, thus extending the result.

Knuth is an ACM-ICPC master and provides a modified pseudocode implementation about the insertion sort for you.His modified algorithm for an array of sortable items AA (11-based array) can be expressed as:

 

Given the parameter kk, you are asked to count the number of distinct permutations of 11 to nn meeting the condition that, after his modified insertion sort, each permutation would become an almost sorted permutation. He notes that a permutation of 11 to nn is almost sorted if the length of its longest increasing subsequence is at least (n - 1)(n−1).

Input

The input contains several test cases, and the first line contains a positive integer TTindicating the number of test cases which is up to 50005000.

For each test case, the only line contains three integers n, kn,k and qq indicating the length of the permutations, the parameter in his implementation and a prime number required for the output respectively, where 1 \leq n, k \leq 501≤n,k≤50 and 10^8 \leq q \leq 10^9108≤q≤109.

Output

For each test case, output a line containing "Case #x: y" (without quotes), where \text{x}x is the test case number starting from 11, and \text{y}y is the remainder of the number of permutations which meet the requirement divided by qq.

Note

In the first sample case, we can discover 1010permutations which meet the condition, and they are listed as follows:

  • [1, 2, 3, 4][1,2,3,4];
  • [1, 2, 4, 3][1,2,4,3];
  • [1, 3, 2, 4][1,3,2,4];
  • [1, 3, 4, 2][1,3,4,2];
  • [1, 4, 2, 3][1,4,2,3];
  • [2, 1, 3, 4][2,1,3,4];
  • [2, 3, 1, 4][2,3,1,4];
  • [2, 3, 4, 1][2,3,4,1];
  • [3, 1, 2, 4][3,1,2,4];
  • [4, 1, 2, 3][4,1,2,3].

样例输入复制

4
4 1 998244353
4 2 998244353
4 3 998244353
4 4 998244353

样例输出复制

Case #1: 10
Case #2: 14
Case #3: 24
Case #4: 24

题目来源

ACM-ICPC Shenyang Oniste 2018

求1-n有多少个排列使得前k个有序之后最长上升子序列>=n-1。

分四种情况:

1、排列完前k个数,排列整体有序。答案为k!,因为前k个数只有k!中排列。

2、排序完,前k个数是1-k,后面最长上升子序列为n-k-1,答案为k!*(n-k-1)^2.有一个结论,1-n排列使得最长上升子序列为n-1的排法有(n-1)^2种。

3、排序前k个后,前k个数有一个替换到后面去,有k!*k(选出哪一个)*(n-k)(插入的位置),当然插入前后n-k个有序。

4、排序前k个后,k被替换为大于等于k+2的数,为k!*(n-k-1),后n-k个一定有序。

#include <algorithm>    //STL通用算法
#include <bitset>     //STL位集容器
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>     //复数类
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>      //STL双端队列容器
#include <exception>    //异常处理类
#include <fstream>
#include <functional>   //STL定义运算函数(代替运算符)
#include <limits>
#include <list>      //STL线性列表容器
#include <map>       //STL 映射容器
#include <iomanip>
#include <ios>      //基本输入/输出支持
#include<iosfwd>     //输入/输出系统使用的前置声明
#include <iostream>
#include <istream>     //基本输入流
#include <ostream>     //基本输出流
#include <queue>      //STL队列容器
#include <set>       //STL 集合容器
#include <sstream>    //基于字符串的流
#include <stack>      //STL堆栈容器    
#include <stdexcept>    //标准异常类
#include <streambuf>   //底层输入/输出支持
#include <string>     //字符串类
#include <utility>     //STL通用模板类
#include <vector>     //STL动态数组容器
#include <cwchar>
#include <cwctype>
#define ll long long
using namespace std;
//priority_queue<int,vector<int>,less<int> >q;
int dx[]= {-1,1,0,0,-1,-1,1,1};
int dy[]= {0,0,-1,1,-1,1,1,-1};
const int maxn = 1000+66;
//const ll mod=1e9+7;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
int n,m;
ll v[maxn];
void init(int mods)
{
    v[0]=v[1]=1;
    for(int i=2;i<=56;i++)
    {
        v[i]=v[i-1]*i%mods;
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    int cnt=0;
    while(t--)
    {
        int mod1,k;
        scanf("%d %d %d",&n,&k,&mod1);
        k=min(n,k);
        init(mod1);
        ll ans=(ll)v[k]*(1+(n-k-1)*(n-k-1) +k*(n-k)+(n-k-1))%mod1;
        printf("Case #%d: %lld\n",++cnt,ans%mod1);
    }
}

参考

https://acm.ecnu.edu.cn/wiki/index.php?title=2018_ACM-ICPC_Shenyang_Regional_Onsite#Problem_C

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章