题解 「2017 山东一轮集训 Day7」逆序对
Description
给定 $ n, k $,请求出长度为 $ n $ 的逆序对数恰好为 $ k $ 的排列的个数。答案对 $ 10 ^ 9 + 7 $ 取模。
对于一个长度为 $ n $ 的排列 $ p $,其逆序对数即满足 $ i < j $ 且 $ p_i > p_j $ 的二元组 $ (i, j) $ 的数量。
一行两个整数 $ n, k $。
一行,表示答案。
对于 $ 20% $ 的数据,$ n, k \leq 20 $;
对于 $ 40% $ 的数据,$ n, k \leq 100 $;
对于 $ 60% $ 的数据,$ n, k \leq 5000 $;
对于 $ 100% $ 的数据,$ 1 \leq n, k \leq 100000, 1 \leq k \leq \binom{n}{2} $。
Solution
可以想到,对于一个排列 \(p\) ,假设 \(s_i\) 表示以 \(i\) 为右端点的逆序对个数,那么可以看出一个 \(s_{1,2,...,n}\) 对应一个唯一的 \(p\) ,而一个 \(s_{1,2,...,n}\) 合法当且仅当 \(\forall i,s_i\le i-1\)。
可以想到我们可以容斥,即枚举哪些点 \(s_i\) 越界了。那么,我们也就只需要求出
\]
的前面 \(k\) 项。
这个时候我们就有两种办法,一种是用多项式,取 \(\ln\) ,然后用 \(\ln(1-x)=\sum_{j=1}^{\infty} -\frac{x^j}{j}\) \(\Theta(k\log k)\) 直接多项式 \(\ln,\exp\) 算出来,考场上我就写的这个,不过原题要写任意模数 NTT,估计不是很好写,而且常数很大,可以拿头过。
还有另外一种 \(\Theta(k\sqrt k)\) 做法。你发现选出一个 \(\{1,2,...,n\}\) 的集合还有另外一种选法,即假设你现在有一个递减序列,你每次有两种选择:
整体加 \(1\)
整体加 \(1\) 并在后面增加一个 \(1\)
那么,我们就可以进行 dp 了,因为考虑到我们最多使用 \(\sqrt k\) 次操作 \(2\),所以,我们可以设 \(f_{i,j}\) 表示在经过 \(i\) 此操作 \(2\) 后数字总和为 \(j\) 的方案数。
可以得到转移式:
\]
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define mod 1000000007
#define MAXN 200005
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
int n,k,upp = 2e5,fac[MAXN],ifac[MAXN],f[505][MAXN];
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int qkpow (int a,int b){
	int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
	return res;
}
void Sub (int &a,int b){a = dec (a,b);}
void Add (int &a,int b){a = add (a,b);}
int binom (int a,int b){return a >= b ? mul (fac[a],mul (ifac[b],ifac[a - b])) : 0;}
int F[MAXN];
signed main(){
	read (n,k);int up = 500;
	fac[0] = 1;for (Int i = 1;i <= upp;++ i) fac[i] = mul (fac[i - 1],i);
	ifac[upp] = qkpow (fac[upp],mod - 2);for (Int i = upp;i;-- i) ifac[i - 1] = mul (ifac[i],i);
	f[0][0] = 1;
	for (Int i = 1;i <= up;++ i)
		for (Int j = 0;j <= k;++ j){
			if (j >= i) Add (f[i][j],add (f[i][j - i],f[i - 1][j - i]));
			if (j >= n + 1) Sub (f[i][j],f[i - 1][j - n - 1]);
		 }
	for (Int S = 0;S <= k;++ S)
		for (Int i = 0;i <= up;++ i)
			if (i & 1) Sub (F[S],f[i][S]);
			else Add (F[S],f[i][S]);
	int ans = 0;
	for (Int S = 0;S <= k;++ S) Add (ans,mul (F[S],binom (k - S + n - 1,n - 1)));
	write (ans),putchar ('\n');
	return 0;
}
												
											题解 「2017 山东一轮集训 Day7」逆序对的更多相关文章
- 【LOJ6077】「2017 山东一轮集训 Day7」逆序对 生成函数+组合数+DP
		
[LOJ6077]「2017 山东一轮集训 Day7」逆序对 题目描述 给定 n,k ,请求出长度为 n的逆序对数恰好为 k 的排列的个数.答案对 109+7 取模. 对于一个长度为 n 的排列 p ...
 - loj #6077. 「2017 山东一轮集训 Day7」逆序对
		
#6077. 「2017 山东一轮集训 Day7」逆序对 题目描述 给定 n,k n, kn,k,请求出长度为 n nn 的逆序对数恰好为 k kk 的排列的个数.答案对 109+7 10 ^ 9 ...
 - 「2017 山东一轮集训 Day7」逆序对
		
题解: 满满的套路题.. 首先显然从大到小枚举 然后每次生成的逆序对是1----(i-1)的 这样做dp是nk的 复杂度太高了 那我们转化一下问题 变成sigma(ai (ai<i) )= ...
 - LOJ6077「2017 山东一轮集训 Day7」逆序对 (生成函数+多项式exp?朴素DP!)
		
题面 给定 n , k n,k n,k ,求长度为 n n n 逆序对个数为 k k k 的排列个数,对 1 e 9 + 7 \rm1e9+7 1e9+7 取模. 1 ≤ n , k ≤ 100 ...
 - loj6077. 「2017 山东一轮集训 Day7」逆序对
		
题目描述: loj 题解: 容斥+生成函数. 考虑加入的第$i$个元素对结果的贡献是$[0,i-1]$,我们可以列出生成函数. 长这样:$(1)*(1+x)*(1+x+x^2)*--*(1+x+x^2 ...
 - LOJ #6119. 「2017 山东二轮集训 Day7」国王
		
Description 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当 ...
 - loj6119 「2017 山东二轮集训 Day7」国王
		
题目描述 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当这条路径上的工 ...
 - loj #6079. 「2017 山东一轮集训 Day7」养猫【最大费用最大流】
		
首先假设全睡觉,然后用费用流考虑平衡要求建立网络流 把1~n的点看作是i-k+1~k这一段的和,连接(i,i+k,1,e[i]-s[i]),表示把i改成吃饭,能对i~i+k-1这一段的点产生影响:然后 ...
 - LOJ6079「2017 山东一轮集训 Day7」养猫
		
养ImmortalCO k可重区间问题 的增强版:有上下界! 直接都选择s[i],然后再把一些调整到e[i] 考虑通过最大流的“最大”,使得至少每k个有me个e, 通过最大流的“上界”,限制每k个最多 ...
 
随机推荐
- IMO 2021 第一题题解及相关拓展问题分析
			
IMO 2021 第 1 题: 设整数 n ≥ 100.伊凡把 n, n + 1, ..., 2n 的每个数写在不同的卡片上.然后他将这 n + 1 张卡片打乱顺序并分成两堆.证明:至少有一堆中包含两 ...
 - Mysql for Mac 安装及环境配置
			
一.下载及安装 首先去官网下载mac对应版本的Mysql,尾缀为.dmg的程序包 下载地址:https://dev.mysql.com/downloads/mysql/ 下载完毕后,一步步傻瓜式安装即 ...
 - Python文件(File)及读写操作及生成器yield
			
open函数在内存中创建缓存区,将磁盘上的内容复制到此处.文件内容读入到文件对象缓冲区后,文件对象将缓冲区视为非常大的列表,其中每个元素都有一个索引.文件对象按字节(大约每个字符)来对文件对象缓冲区索 ...
 - Nginx+Tomcat+Memcached实现session共享
			
实验环境: server1:nginx tomcat memcached server2:tomcat memcached Session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入 ...
 - JS 之 每日一题 之 算法 ( 划分字母区间  )
			
题目详解: 字符串 S 由小写字母组成.我们要把这个字符串划分为尽可能多的片段,同一个字母只会出现在其中的一个片段.返回一个表示每个字符串片段的长度的列表. 例子: 示例 1: 输入:S = &quo ...
 - Windows内核-7-IRP和派遣函数
			
Windows内核-7-IRP和派遣函数 IRP以及派遣函数是Windows中非常重要的概念.IRP 是I/O Request Pocket的简称,意思是I/O操作的请求包,Windows中所有Use ...
 - 1.3w字,一文详解死锁!
			
死锁(Dead Lock)指的是两个或两个以上的运算单元(进程.线程或协程),都在等待对方停止执行,以取得系统资源,但是没有一方提前退出,就称为死锁. 1.死锁演示 死锁的形成分为两个方面,一个是使用 ...
 - Spring事物入门简介及AOP陷阱分析
			
转载请注明出处: https://www.cnblogs.com/qnlcy/p/15237377.html 一.事务的定义 事务(Transaction),是指访问并可能更新数据库中各种数据项的一个 ...
 - 利用job提升马哈鱼数据血缘分析效率
			
利用job提升马哈鱼数据血缘分析效率 一.Job基本知识 前面文章中已介绍马哈鱼的基本功能,其中一个是job,job其实是一个任务集合处理的概念,就是让用户通过job,可以一次递交所有需要处理的 SQ ...
 - C# 爬虫框架实现 概述
			
目录: C# 爬虫框架实现 概述 C# 爬虫框架实现 流程_爬虫结构/原理 C# 爬虫框架实现 流程_各个类开发 C# 爬虫框架实现 流程_遇到的问题 C# 爬虫框架实现 后记 C#爬虫框架实现 源代 ...