【CF886E】Maximum Element
考虑正难则反,答案即为\(n!-\text{返回值为n的排列数}\)
一个排列的返回值为\(n\),当且仅当在\(n\)出现之前没有一个数后面有连续\(k\)个小于它的数
设\(f_i\)表示\(1\)到\(i\)的排列中,没有任何一个数后面有连续\(k\)个小于它的数
枚举\(i\)的位置,则有
\]
即把\(i\)放在倒数第\(j\)个位置,从\(1\)到\(i-1\)中选\(j-1\)个数排列在\(i\)后面,剩下\(i-j\)个个数放在\(i\)前面并且保证合法
把排列数打开,就变成了\(f_i=(i-1)!\sum_{j=1}^{k}\frac{f_{i-j}}{(i-j)!}\)
维护一下\(\frac{f_i}{i!}\)的前缀和就可以快速转移了
枚举一下\(n\)所在的位置,返回值为\(n\)的排列数即为
\]
代码
#include<bits/stdc++.h>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const int mod=1e9+7;
const int maxn=1e6+5;
int pre[maxn],fac[maxn],ifac[maxn],inv[maxn],f[maxn];
int n,m;
inline int C(int n,int m) {
if(n<m) return 0;
return 1ll*fac[n]*ifac[n-m]%mod*ifac[m]%mod;
}
inline int qm(int x) {return x>=mod?x-mod:x;}
inline int dqm(int x) {return x<0?x+mod:x;}
inline int calc(int l,int r) {
if(l<=0) return pre[r];
return dqm(pre[r]-pre[l-1]);
}
int main() {
n=read(),m=read();fac[0]=ifac[0]=inv[1]=1;
for(re int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod;
for(re int i=2;i<=n;i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for(re int i=1;i<=n;i++) ifac[i]=1ll*ifac[i-1]*inv[i]%mod;
f[0]=1;pre[0]=1;
for(re int i=1;i<n;i++) {
f[i]=1ll*calc(i-m,i-1)*fac[i-1]%mod;
pre[i]=qm(pre[i-1]+1ll*f[i]*ifac[i]%mod);
}
int ans=0;
for(re int i=1;i<=n;i++)
ans=qm(ans+1ll*f[i-1]*C(n-1,i-1)%mod*fac[n-i]%mod);
printf("%d\n",dqm(fac[n]-ans));
return 0;
}
【CF886E】Maximum Element的更多相关文章
- 【CF886E】Maximum Element DP
[CF886E]Maximum Element 题意:小P有一个1-n的序列,他想找到整个序列中最大值的出现位置,但是他觉得O(n)扫一遍太慢了,所以它采用了如下方法: 1.逐个遍历每个元素,如果这个 ...
- 【CF888E】Maximum Subsequence(meet in the middle)
[CF888E]Maximum Subsequence(meet in the middle) 题面 CF 洛谷 题解 把所有数分一下,然后\(meet\ in\ the\ middle\)做就好了. ...
- 【CF888E】Maximum Subsequence 折半搜索
[CF888E]Maximum Subsequence 题意:给你一个序列{ai},让你从中选出一个子序列,使得序列和%m最大. n<=35,m<=10^9 题解:不小心瞟了一眼tag就一 ...
- 【数组】Maximum Subarray
题目: Find the contiguous subarray within an array (containing at least one number) which has the larg ...
- 【leetcode】Maximum Subarray (53)
1. Maximum Subarray (#53) Find the contiguous subarray within an array (containing at least one nu ...
- 【leetcode】Majority Element
题目概述: Given an array of size n, find the majority element. The majority element is the element that ...
- 【leetcode】Maximum Gap
Maximum Gap Given an unsorted array, find the maximum difference between the successive elements in ...
- 【leetcode】Maximum Subarray
Maximum Subarray Find the contiguous subarray within an array (containing at least one number) which ...
- 【leetcode】Maximum Gap(hard)★
Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...
随机推荐
- java 重新学习 (五)
Set 集合 一.HashSet按照Hash算法存储集合元素(hashCode方法获取hashCode值,根据hashCode值获取元素位置,通过equals判断对象是否相等并且hashCode值是否 ...
- python 模拟双色球输出
编写Python函数:完成一个双色球彩票的模拟生成过程, 其中前六个为红色球,数字范围1-33,不可重复.最后一个为蓝色球 1-16. import random #red_nums是采集红色球的数字 ...
- [已解决]报错: Creating Server TCP listening socket 127.0.0.1:6379: bind: No error
问题: windows下安装Redis第一次启动报错: [2368] 21 Apr 02:57:05.611 # Creating Server TCP listening socket 127.0. ...
- Python之内建函数
常用内置函数: abs(): 绝对值 divmod(): 取商和模 pow(): 指数运算 round(): 返回浮点数 callable(): 判断函数是否可调用 isinstance(): ...
- sed以及awk
一.sed sed是一种流编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时 缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的 内容,处理完成后,把缓 ...
- 代理-jdk动态代理
1.基于接口的实现,要jdk动态代理的类必须要实现一个接口: 2.中介类:实现了InvocationHandler,并重写这个接口的 方法(public Object invoke(Object pr ...
- 64位 __int 与 long long写法
在做ACM题时,经常都会遇到一些比较大的整数.而常用的内置整数类型常常显得太小了:其中long 和 int 范围是[-2^31,2^31),即-2147483648~2147483647.而unsig ...
- java笔试手写算法面试题大全含答案
1.统计一篇英文文章单词个数.public class WordCounting {public static void main(String[] args) {try(FileReader fr ...
- node js实战:带数据库,加密的注册登录表单
demo 注册效果: 登陆效果: 数据库截图: 数据库操作 db.js //这个模块里面封装了所有对数据库的常用操作 var MongoClient = require('mongodb ...
- centos 单用户登陆模式操作
在centos中因为安装java而配置 jdk环境变量的原因,对/etc/profile文件进行了编辑 错误的环境变量配置导致在第一次修改profile文件并保存后,执行source /etc/pro ...