$ \color{#0066ff}{ 题目描述 }$

从前有一个叫Petya的神仙,嫌自己的序列求max太慢了,于是将序列求max的代码改成了下面这个样子:

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++;
if(offset==k)return ans;
}
}
return ans;
}
//大括号换行,无多余空格,by wucstdio

这个函数的原理是,如果碰到一个数后面连续的\(k\)个数都比它小,那么就把这个数当做序列的最大值。

然而很显然,这份代码是错的。这位\(Petya\)神仙对它出错的情况很感兴趣。于是他找到了同为神仙的你,让你求有多少长度为\(n\)的排列,这个函数会返回错误的结果,即返回值不是\(n\)。由于答案过大,你只需要输出这个数对\(10^9+7\)取模的结果。

\(\color{#0066ff}{输入格式}\)

一行两个正整数\(n\)和\(k\),表示排列的长度和上面那份代码里的\(k\)。

\(\color{#0066ff}{输出格式}\)

一行一个整数,表示答案对\(10^9+7\) 取模后的值。

\(\color{#0066ff}{输入样例}\)

5 2

5 3

6 3

\(\color{#0066ff}{输出样例}\)

22

6

84

\(\color{#0066ff}{数据范围与提示}\)

Permutations from second example:

\([4,1,2,3,5]\) , $[4,1,3,2,5] $, \([4,2,1,3,5] ,\) $[4,2,3,1,5] $, $[4,3,1,2,5] $, \([4,3,2,1,5]\) .

\(\color{#0066ff}{题解}\)

如果正着算,比如 4 2 1 6 5 3,k=2,那么会出现两个符合条件的,但是我们只算一次,所以这样不好算

我们考虑单步容斥,用总数\(n!\)减去最大值是n的

考虑排列中n的位置,那么n前面的数不能出现题目所说的情况

于是我们设\(f[i]\)为长度为i的排列,不会出现一个数后面有k个比它小的数的方案数

还是考虑i的位置来转移,因为i是最大的,所以显然转移为\(f_i=\sum_{j=i-k+1}^if_{j-1}\C_{i-1}^{i-j}*(i-j)!=(i-1)!*\sum_{j=i-k}^{i-1}\frac{f_j}{j!}\)

显然后面的东西可以前缀和优化一下,于是我们可以\(O(n)\)求出f数组!

然后开始统计答案,枚举n的位置i\(ans=\sum_{i=1}^nf_{i-1}*\C_{n-1}^{n-i}*(n-i)!=(n-1)!*\sum_{i=1}^n\frac{f_{i-1}}{(i-1)!}\)

直接线性统计答案即可

#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 5e6 + 10;
const int mod = 1e9 + 7;
int n, k;
LL fac[maxn], inv[maxn];
LL f[maxn], s[maxn];
LL ksm(LL x, LL y) {
LL re = 1LL;
while(y) {
if(y & 1) re = re * x % mod;
x = x * x % mod;
y >>= 1;
}
return re;
}
int main() {
n = in(), k = in();
fac[0] = 1;
for(LL i = 1; i <= n; i++) fac[i] = fac[i - 1] * i % mod;
inv[n] = ksm(fac[n], mod - 2);
for(LL i = n - 1; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1) % mod;
f[0] = s[0] = 1;
for(int i = 1; i <= n; i++) {
f[i] = (fac[i - 1] * (s[i - 1] - (i - k - 1 >= 0? s[i - k - 1] : 0) + mod)) % mod;
s[i] = (f[i] * inv[i] % mod + s[i - 1]) % mod;
}
LL ans = 0;
for(int i = 1; i <= n; i++) (ans += fac[n - 1] * f[i - 1] % mod * inv[i - 1] % mod) %= mod;
printf("%lld", (fac[n] - ans + mod) % mod);
return 0;
}

CF886E Maximum Element的更多相关文章

  1. 【CF886E】Maximum Element DP

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

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

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

  3. Codeforces 889C Maximum Element(DP + 计数)

    题目链接  Maximum Element 题意  现在有这一段求序列中最大值的程度片段: (假定序列是一个1-n的排列) int fast_max(int n, int a[]) { int ans ...

  4. 【CF886E】Maximum Element

    题目 考虑正难则反,答案即为\(n!-\text{返回值为n的排列数}\) 一个排列的返回值为\(n\),当且仅当在\(n\)出现之前没有一个数后面有连续\(k\)个小于它的数 设\(f_i\)表示\ ...

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

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

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

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

  7. The 2018 ACM-ICPC Chinese Collegiate Programming Contest Maximum Element In A Stack

    //利用二维数组模拟 #include <iostream> #include <cstdio> #include <cstring> #include <s ...

  8. Codeforces889C. Maximum Element

    $n \leq 2000000$的排列,问有多少满足:存在个$i$,使得$p_i \neq n$,且$p_j<p_i,j \in [i+1,i+K]$,$K \leq 2000000$是给定常数 ...

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

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

随机推荐

  1. xUtils怎么post请求上传json数据

    InfoSmallCodeBinding smallCode = new InfoSmallCodeBinding(); smallCode.setSmallCode("测试"); ...

  2. 【279】◀▶ Python 运算符说明

    参考:Python 运算符说明 目录: 一.算术运算符 二.比较(关系)运算符 三.赋值运算符 四.位运算符 五.逻辑运算符 六.成员运算符 七.身份运算符 八.运算符优先级 一.Python 算术运 ...

  3. 08-Location总结图解

    URI解析  首先要判断有没有精准匹配,能不能精准匹配.计算机里面没有什么这种差不多这种东西.跟人聊天才说差不多,最近过得怎么样啊,还行吧,差不多吧,这个不多是多还是不多啊. 预定义库->Gen ...

  4. MyGeneration代码生成工具

    使用MyGeneration 生成代码:转自http://www.cnblogs.com/jack-liang/archive/2011/08/18/2144066.html 我们经常用数据访问层和业 ...

  5. Codeforces 1142D Foreigner (DP)

    题意:首先定义了一种类数(标志数) 1:1到9都是标志数. 2:若x / 10是标志数,假设x /10在标志数中的排名是k, 若x的个位数小于k % 11, 那么x也是标志数. 现在给你一个字符串,问 ...

  6. 线程dump

    当应用程序运行变慢或者发生故障时,可能通过分析java的Thread Dumps得到分析他们得到阻塞和存在瓶颈的线程. 线程堆栈是虚拟机中线程(包括锁)状态的一个瞬间状态的快照,即系统在某一个时刻所有 ...

  7. Docker01 centos系统安装、centos安装docker、docker安装mongoDB

    1 centos系统安装 本博文是基于 centos6.5 的,利用VMware 虚拟机搭建 centos6.5 系统 1.1 centos6.5资源获取 1.2 安装 1.2.1 新建虚拟机 1.2 ...

  8. WCF4.0 –- RESTful WCF Services

    转自:http://blog.csdn.net/fangxinggood/article/details/6235662 WCF 很好的支持了 REST 的开发, 而 RESTful 的服务通常是架构 ...

  9. Linux nethack

    一.简介 游戏目标:在地下城的最底层取得炎多的护符项链(Amulet of Yendor),并返回最上层,在圣祭坛上供奉给神灵.完成整个游戏的奖赏是,玩家会成为不朽的半神.   二.安装 1)下载源码 ...

  10. linux操作小技巧

    巧妙利用别称 alias,让工作更有效率 在我的个人目录下/home/zdwu,打开.bashrc文件进行修改: 将  ll='ls -alF' 改为 ll='ls -ahlF',是的观察的结果显示更 ...