D. New Year and the Permutation Concatenation 题解翻译+思路解释(官方为主,我为补充)+普通人能看得懂的代码(我照着思路写的哈哈哈)

传送门:http://codeforces.com/contest/1091/problem/D

There are two types of subarrays with length n:
有两种类型的长度为n的子序列

  • They are fully formed from one permutations.
    所组成的元素完全就是来自某一个独立的排列
  • They are a concatenation of a k long suffix of one permutation, and a nk long prefix of the next permutation.
    一个级联(杂交)排列,它里面前k个元素来自某一个排列的后缀部分,后(n-k)个元素来自下一个排列的前缀部分。

There are n! such subarrays of the first type, and they all have the the correct sum.
很显然,有n!个排列是第一种类型的,且数量有n!个。因为是一个独立的排列,所以和一定是所要求的n*(n+1)/2

Let's investigate the second type. Recall the algorithm of finding the next permutation in lexicographical order. We find the longest
让我们探索一下第二种类型。回顾一下按字典序产生下一个排列的算法。我们找到一段降序排列的最长后缀,定义它的长度为k
suffix that is in decreasing order, let its length be 
k.
We swap the preceding element 
x with the smallest one from the decreasing sequence larger than x,
我们把 这段后缀的前一个元素x 和 这段降序后缀中大于x又是最小的那个元素 交换。
and sort the suffix in increasing order.
然后将新后缀按升序排列。
The prefix of length 
n−k−1 is left unchanged, but all longer proper prefixes are different and also change their sum.
作为前缀部分的前(n-k-1)个元素保持不动,但是任何比(n-k-1)更长的前缀排列和原来的相比都不一样了包括它们的元素和

Coming back to our problem, if the suffix of length k is in decreasing order,
回归正题,如果当前独立排列的长度为k的后缀是按降序排列
than the prefix of length 
nk of the next permutation has different sum from the prefix of the same length of the current permutation,
那么下一个排列的前(n-k)个元素就拥有了和当前排列相同长度的前缀排列不同的和 (降序一定改变下一个排列前(n-k)个元素的布局)。
hence the subarray has incorrect sum.
因此这个杂交排列的和就一定不是我们期待的n*(n+1)/2了(由于某一个相同的元素跑到下一个独立排列的前缀当中)
Conversely, if the suffix of length k is not in decreasing order, then the prefix of length 
nk of the next permutation equals to the prefix of the current permutation, and its sum is n(n+1)/2.
相反的,如果当前独立排列的长度为k的后缀不按降序排列,下一个排列的前(n-k)个元素就和当前排列相同长度的前缀排列一样,杂交排列的和就是我们期待的n*(n+1)/2

To find the answer, we must thus subtract the number of suffixes of all permutations that are decreasing.
为了找出答案,我们一定要找出所有按照降序排列的后缀个数(长度从1到(n-1)) 
How many of them are there for a fixed k
?
如果告诉我们后缀长度是k,那么这样的后缀到底有多少个呢?
This is simple – we choose the first 
nk elements freely, and permute them.
很简单,我们自由选择前(n-k)个元素,然后让他们进行全排列
The rest has to be sorted in a particular way.
剩下的部分需要按照降序排列
Hence the number of bad subarrays coming from a suffix of length 
k equals n!/k!.
所以无效后缀的个数(在后缀长度等于k的前提下)就是n
!/k!:

                                                 C_{n}^{k}*(n-k)!=n!/k!

Convince yourself that this approach works correctly even for the last permutation, where there is no next permutation to concatenate its suffixes with.
你还要确保这个方法能正确工作即使是后缀在最后一个独立排列的时候,因为它后面没有能和它的后缀连接的独立排列了

The answer is:

其实可以这样子推导:
考虑进第一种情况,然后把后缀问题转化成从哪个点开始的排列可以达成目的,当然你还是要通过上面的讲解来理解什么时候能达成目的——后序是降序序列
物理上不允许作为前缀的起始点的个数=(n-1)…………………………………………………………①
那么所有可以作为前缀的起始点的个数= n*n! - (n-1)…………………………………………………②
逻辑上不允许作为前缀的起始点的个数= ………………③
这个公式里为什么要每次都减1呢?
因为降序后缀肯定是会涉及到最后一个独立排列(刚好是全降序)里面的,然而我们之前已经把它归为物理不允许前缀起始点了,所以要减去这种情况。
②-③ 就得到了:

This can be calculated in O(n) without the need of modular division.
我的代码只能做到O(n),不能做到不用取模运算。代码在下方:

There is also a simple recurrence counting the same answer, found by arsijo:
另一位大佬的方式:重复计数求值法

d(n)=(d(n−1)+(n−1)!−1)⋅n

接下来是我按照第一种正式的思路写出来的代码:



 

/*SE:wn------王宁*/
#include <bits/stdc++.h>
using namespace std;

#define ll long long
const ll MOD = (ll)998244353;
ll n;

int main()
{
    scanf("%lld", &n);
    ll res = n;
    ll i,j,k,tmp=1;
    for(i=2;i<=n;++i) res=res*i%MOD;
    for( k=n; k>=2 ; --k )
    {
    	tmp=tmp*k%MOD;
		res=(res-tmp+MOD)%MOD;
	}
	cout<<res;
    return 0;
}

转载请注明出处。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值