题目链接  Maximum Element

题意  现在有这一段求序列中最大值的程度片段:

(假定序列是一个1-n的排列)

int fast_max(int n, int a[]) {
int ans = 0;
int offset = 0;
for (int i = 0; i < n; ++i)
if (ans < a[i]) {
ans = a[i];
offset = 0;
} else {
offset = offset + 1;
if (offset == k)
return ans;
}
return ans;
}

显然这段程序是错误的……有很多可以X掉这段程序的排列

求这样的排列有多少个。

题目是让我们求符合这样条件的排列个数:

1、存在某个数,他比前面的数都大并且小于$n$;

2、他比他后面$k$个数都要大。

假设“中间这个数”为$cnt$

假设$D(i)$为满足$p(i) = i$的这样的排列个数

我们可以把$D(i)$的求解分成两个过程。

1、计算$cnt$等于$i - 1$的排列个数

2、计算$cnt$不等于$i - 1$的排列个数

首先如果$i <= k + 1$,则$D(i) = 0$

当这个序列的$cnt$为$i - 1$时,只要满足$i - 1$和$i$之间的数大于等于$k$个即可。

于是对于$i - 1$这个数的位置的选择,我们有$i - k - 1$种。

然后呢,除了$i - 1$和$i$这两个数,其他数的位置随意(因为$i$排在最后,所以排在$i - 1$前的数字都比$i - 1$要小)

所以当前这种情况对答案的贡献为$(i - k - 1) * (i - 2)!$

考虑另外一种情况。

当$cnt$不等于$i - 1$的时候,一定有$cnt < i - 1$

设$i - 1$所在位置为$pos$,我们把$i - 1$之前的$pos - 1$个数离散化成一个$1$到$pos - 1$的排列

然后在这个排列的最后加上$pos$,就构成了一个$1$到$pos$并且以$pos$结尾的排列

那么如果这个排列是符合要求的,那么整个排列也是符合要求的。

于是我们枚举$i - 1$的位置$pos$,满足条件的位置为$i - k <= pos <= i - 1$

我们在剩下的$i - 2$个数中选出$pos - 1$个放到前$pos - 1$个位置,然后乘上$D(pos)$。

然后还要乘上$(i - pos - 1)!$,因为$i - 1$到$i$之间的数都是随意乱放的……

于是当前这种情况对答案的贡献为

于是我们终于推出了D(n)的公式

最后的答案怎么计算呢

我们假设$n$的位置为$pos$

那么当$p(pos) = n$的时候,前pos个数的方案数为$D(pos) * C(n - 1, pos - 1)$

后$n - pos$个数的方案数为$(n - pos)!$

所以当$p(pos) = n$的时候对答案的贡献为$D(pos) * C(n - 1, pos - 1)*(n - pos)!$

枚举$pos$,累加即可。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i) const int N = 1e6 + 10;
const int mod = 1e9 + 7; int n, k;
int f[N], s[N];
int fac[N], inv[N];
int ans = 0; inline int Pow(int a, int b, int mod){
int ret(1);
for (; b; b >>= 1, a = (1ll * a * a) % mod) if (b & 1) (ret = 1ll * ret * a) % mod;
return ret;
} void init(){
fac[0] = 1;
rep(i, 1, 1e6 + 1) fac[i] = 1ll * fac[i - 1] * i % mod;
rep(i, 1, 1e6 + 1) inv[i] = Pow(fac[i], mod - 2, mod);
} inline void up(int &a, int b) { a = (0ll + a + b) % mod;}
inline void mulup(int &a, int b){ a = 1ll * a * b % mod;} int main(){ scanf("%d%d", &n, &k);
init(); rep(i, k + 2, n){
f[i] = i - k - 1;
up(f[i], s[i - 1] - s[i - k - 1]);
mulup(f[i], fac[i - 2]);
s[i] = (0ll + s[i - 1] + 1ll * f[i] * inv[i - 1] % mod) % mod;
} rep(i, 1, n) up(ans, (int)1ll * f[i] * fac[n - 1] % mod * inv[i - 1] % mod);
printf("%d\n", ans);
return 0;
}

  

Codeforces 889C Maximum Element(DP + 计数)的更多相关文章

  1. 【CF886E】Maximum Element DP

    [CF886E]Maximum Element 题意:小P有一个1-n的序列,他想找到整个序列中最大值的出现位置,但是他觉得O(n)扫一遍太慢了,所以它采用了如下方法: 1.逐个遍历每个元素,如果这个 ...

  2. Codeforces Round #445 Div. 1 C Maximum Element (dp + 组合数学)

    题目链接: http://codeforces.com/contest/889/problem/C 题意: 给你 \(n\)和 \(k\). 让你找一种全排列长度为\(n\)的 \(p\),满足存在下 ...

  3. Codeforces 886E Maximum Element 组合数学 + dp

    我们定义dp[ i ]表示长度为 i 的序列, 最后没有一个==k的时候返回的方案数, 也就是最后强制返回 i 的方案数. 我们能得到dp方程   dp[ i ] = sum(dp[ i - j - ...

  4. Codeforces 702A Maximum Increase(dp)

    题目链接:http://codeforces.com/problemset/problem/702/A 题意: 给你N个数,a[0], a[1], a[2], ....., a[n-1],让你找出最长 ...

  5. Codeforces - 102222A - Maximum Element In A Stack - 模拟

    https://codeforc.es/gym/102222/problem/F 注意到其实用unsigned long long不会溢出. #include<bits/stdc++.h> ...

  6. Tetrahedron(Codeforces Round #113 (Div. 2) + 打表找规律 + dp计数)

    题目链接: https://codeforces.com/contest/166/problem/E 题目: 题意: 给你一个三菱锥,初始时你在D点,然后你每次可以往相邻的顶点移动,问你第n步回到D点 ...

  7. 【CodeForces】889 C. Maximum Element 排列组合+动态规划

    [题目]C. Maximum Element [题意]给定n和k,定义一个排列是好的当且仅当存在一个位置i,满足对于所有的j=[1,i-1]&&[i+1,i+k]有a[i]>a[ ...

  8. 动态规划(DP计数):HDU 5116 Everlasting L

    Matt loves letter L.A point set P is (a, b)-L if and only if there exists x, y satisfying:P = {(x, y ...

  9. Codeforces 484B Maximum Value(高效+二分)

    题目链接:Codeforces 484B Maximum Value 题目大意:给定一个序列,找到连个数ai和aj,ai%aj尽量大,而且ai≥aj 解题思路:类似于素数筛选法的方式,每次枚举aj,然 ...

随机推荐

  1. wamp开发环境配置之配置Apache虚拟主机

    网站建设人员在本地测试时,常常不是一个网站,那怎么能像输入域名一样在地址栏上面输入“域名”就能本地访问该网站呢?这里就要配置Apache虚拟主机了! 1.找到apache\conf\httpd.con ...

  2. 实验二 JSP基本动态元素的使用

    实验二  JSP基本动态元素的使用 实验性质:验证性          实验学时:  2学时      实验地点: 一 .实验目的与要求 1.掌握JSP中声明变量.定义方法.java程序片及表达式的使 ...

  3. day 35 补充

      MySQL数据库初识   MySQL数据库 本节目录 一 数据库概述 二 MySQL介绍 三 MySQL的下载安装.简单应用及目录介绍 四 root用户密码设置及忘记密码的解决方案 五 修改字符集 ...

  4. loc与iloc函数的使用

    Pandas中loc和iloc函数用法详解(源码+实例)  https://blog.csdn.net/w_weiying/article/details/81411257 Pandas中loc,il ...

  5. nrf51822微信开发入门学习笔记1:开始前的准备

    参考:(id:love--baby)https://blog.csdn.net/hunhun1122/article/details/68922493 微信硬件平台:https://iot.weixi ...

  6. leetcode-18-remove

    283. Move Zeroes 解题思路: 从nums[0]开始,如果是零就和它后面的第一个非零数交换,不是零就下一位.不贴代码了,比较简单. 27. Remove Element 解题思路: 这道 ...

  7. Makefile基础(三)

    第一章:C语言之Makefile基础(一) 第二章:C语言之Makefile基础(二) 再来看一个简单的例子: [root@localhost linux_c]# cat Makefile foo = ...

  8. loj2031 「SDOI2016」数字配对

    跑最大费用最大流,注意到每次 spfa 出来的 cost 一定是越来越少的,啥时小于 \(0\) 了就停了吧. #include <iostream> #include <cstri ...

  9. 初试webpack打包

    第一次接触webpack,学习了如何用webpack打包,记录一下过程. 1.在项目根目录安装webpack $ npm install webpack --save-dev 2.新建一个webpac ...

  10. oracle结构-内存结构与动态内存管理

    内存结构与动态内存管理 内存是影响数据库性能的重要因素. oracle8i使用静态内存管理,即,SGA内是预先在参数中配置好的,数据库启动时就按这些配置来进行内在分配,oracle10g引入了动态内存 ...