瀋陽區域賽-- 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

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