传送门: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 n−k 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 n−k 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 n−k 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 n−k 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!:

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;
}

转载请注明出处。

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

  1. [cf 1091D]D. New Year and the Permutation Concatenation

    新版题解链接:https://blog.csdn.net/aiqiyizz/article/details/115579003 题意:给n!个n的排列,按字典序从小到大连成一条序列,例如3的情况为:[ ...

  2. HDU 1010题解这是一道简单的DFS加回溯题,看懂后就会对递归和回溯有较深刻的理解。...

    1 #include<iostream> 2 #include<cstdio> 3 4 using namespace std; 5 6 char s[7][7]; //将变量 ...

  3. 混合个人训练第四十六场(A,B题解) A 数论线代全家桶 (all) B: 看星星 (stars)

    A 数论线代全家桶 (all) 题意如图. 思路: 首先发现 1 = 1 * 1 * 1; n=1; 4 = 1 * 4 * 1; n=2; 72 = 4 * 18=4 * 9 * 2; n=3; 2 ...

  4. 【最新合集】PAT乙级最优题解(题解+解析+代码)

    以下每道题均是笔者多方对比后, 思考整理得到的最优代码,欢迎交流! pat乙级题解目录 编号 标题 题解 分类 1001 害死人不偿命的(3n+1)猜想 (15分) 9行代码AC 水 1002 写出这 ...

  5. GDUFS 2018信息学院程序设计新手赛(正式赛)Java版题解

    Problem A: HELLO Description <绝地求生>(PUBG) 是一款战术竞技型射击类沙盒游戏 . 该游戏中,玩家需要在游戏地图上收集各种资源,并在不断缩小的安全区域内 ...

  6. 9月——都已经9月了还不好好刷题?。。

    1 UVALive4513 (字符串hash 题目:在一个串中找到至少出现m次的最长的串. 思路:直接hash,然后二分答案. /* * @author: Cwind * http://www.cnb ...

  7. 【chainer速成】chainer图像分类从模型自定义到测试

    文章首发于微信公众号<有三AI> [chainer速成]chainer图像分类从模型自定义到测试 欢迎来到专栏<2小时玩转开源框架系列>,这是我们第八篇,前面已经说过了caff ...

  8. 【面试招聘】非科班的秋招攻略贴

    秋招进程过半,最近很多人看到我的面经的帖子都在询问楼主做什么的,非科班该如何备战秋招,因为实在一个个的回复起来比较麻烦,这里趁着闲暇时光整理了一下自己作为一个非科班的学生是如何准备秋招的过程,供大家参 ...

  9. 回溯法基本思想_LeetCode--回溯法心得

    这两天在刷LeetCode37题解数独时,被这个回溯法折腾的不要不要的,于是我疼定思疼发誓一定要找个能解决这类回溯法的套路出来,方便以后快速解决此类题目.于是我在网上找了两个很经典的回溯法题目--八皇 ...

最新文章

  1. 使用rar备份mysql_用RAR备份源代码_用WSH备份数据库
  2. 动态规划算法-04最长递增子序列问题
  3. mongodb安装_Windows系统安装运行Mongodb服务
  4. wireshark常用选项与功能总结【10分钟成为抓包大师】
  5. apache 软件历史版本查询
  6. python爬虫爬取英文考研词汇
  7. linux下ps ef命令详解,linux中ps -ef命令
  8. Android 启动优化说明、黑白屏处理
  9. 2020java开发面试题
  10. Linux下查看输入设备、获取输入事件的详细方法
  11. 【微信公众号发红包转账】微信公众号上手机网页接收请求,通过公众号给用户发红包 开发流程...
  12. 关于STM32 IAP升级之为什么APP执行要0x2FFE0000这个数值的原因(基于STM32F446RET6)
  13. java热敏POS打印机编程
  14. 服务化系统容量评估和性能保障
  15. Matlab中interp2和interpn的差异
  16. 栾云开 作业 笔记
  17. 恶梦护士 asa_敏捷街上的噩梦2:受控敏捷
  18. 2018年PMP项目管理专业人士资格认证考试回顾总结
  19. 第十一章 “万金油”的String,为什么不好用了
  20. html是如何实现独占一行原理,前端知识(Html)汇总1

热门文章

  1. 360 || 2021校园招聘的一道笔试题思路分享
  2. 玄学小问题之input.focus()没生效的问题
  3. Virtual Box 虚拟机响应慢解决办法
  4. 2018 年博客总结
  5. win7替换桌面图标
  6. 锐捷网络普教中小学“绿色校园网”解决方案
  7. WEMOS D1 R1/R2 [ESP8266] + PCA9685 驱动舵机
  8. 订单中心探索业务系统数据预置助力快交付之路
  9. Mac xmind 8完美破解教程
  10. win10查询计算机ip和用户名和密码,Win10怎么查看ip地址_Win10查看本机ip地址-192路由网...