【计数,DP】CF1081G Mergesort Strikes Back
现有一归并排序算法,但是算法很天才,设了个递归深度上限,如果递归深度到达 \(k\) 则立即返回。其它部分都和正常归并排序一样,递归中点是 \(\lfloor (l+r)/2 \rfloor\),归并每次取两边较小者加入结果。
给定 \(n,k\),求用这个算法对一个均匀随机的排列 \(p\) 排序后,\(p\) 的期望逆序对数是多少,答案对输入的质数取模。\(n,k\le 10^5\)。
技巧:\(\prod 1/\mathrm{siz}_u\)
首先注意到其实就是把那一车长度为 \(n/2^k\) 左右的区间同时拿来归并。
仔细想一想会发现如果选了一个数,它的下一个数比它小,那一定会跟着选下一个数。推下去可以发现就是每个区间的前缀最大值带着一串小兵一起以前缀最大值为关键字排序。
这道题是求“和的期望”,所以自然应该想到拆贡献。考虑两个位置 \(x,y\) 之间产生贡献的期望值是多少。
如果 \(x,y\) 在同一段区间,那由于同一段区间内相对顺序不变(前缀最大值递增),所以 \(x,y\) 为逆序对的概率即为 \(1/2\)。
如果 \(x,y\) 在不同区间,设 \(x\) 所在区间长度为 \(a\),\(y\) 所在区间长度为 \(b\),则贡献期望值显然只和 \(a,b\) 有关。又 \(a,b\) 只有两种取值,外层直接枚举即可。
现在 \(a,b\) 固定了。考虑钦定 \(x\) 在 \(y\) 前面构成逆序对的条件,设 \(x\) 左边的第一个前缀最大值为 \(p\),\(y\) 左边的第一个前缀最大值为 \(q\),则成立的充要条件为:\(B_y<A_x<A_p<B_q,\forall 1\le i<x,A_i<A_p,\forall 1\le j<y,B_j<B_q\)。其它位置可以随便填,无关紧要,这是这种做法正确的基础。
发现我们刚才需要成立的关系形成一棵树!根据经典结论,所有关系都成立的概率为 \(\prod 1/\mathrm{siz}_u\),其中 \(\mathrm{siz}_u\) 表示 \(u\) 的子树大小。
把暴力写出来,是 \(O(ab)\) 的。再推一推发现可以预处理倒数的前缀和优化,就线性了。
注意特判 \(p=x\) 的情况。

点击查看代码
#include <bits/stdc++.h>
#define For(i,a,b) for(int i=a;i<=b;i++)
#define Rev(i,a,b) for(int i=a;i>=b;i--)
#define Fin(file) freopen(file,"r",stdin);
#define Fout(file) freopen(file,"w",stdout);
using namespace std;
const int N=1e5+5; using ll = long long;
int n,K,mod,inv[N],si[N];
int work(int a,int b){
int res=0;
For(i,1,a){
int tt=(b-1-1ll*(i+1)*(si[i+b]-si[i+1]+mod)%mod+mod)%mod;
res=(res+(1ll*inv[2]*(i-1)+1)%mod*inv[i+1]%mod*tt)%mod;
}
return res;
}
int main(){
cin>>n>>K>>mod; K--; K=min(K,18);
inv[1]=1; For(i,2,n+1) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
For(i,1,n+1) si[i]=(si[i-1]+inv[i])%mod;
int a=n>>K,b=a+1,cb=n-(a<<K),ca=(1<<K)-cb;
int ans=(1ll*a*(a-1)/2%mod*ca+1ll*b*(b-1)/2%mod*cb)%mod*inv[2]%mod;
ans=(ans+1ll*ca*(ca-1)%mod*work(a,a))%mod;
ans=(ans+1ll*cb*(cb-1)%mod*work(b,b))%mod;
ans=(ans+1ll*ca*cb%mod*work(a,b))%mod;
ans=(ans+1ll*cb*ca%mod*work(b,a))%mod;
cout<<ans<<'\n';
return 0;
}
【计数,DP】CF1081G Mergesort Strikes Back的更多相关文章
- CF1081G Mergesort Strikes Back
题目大意: 给定\(n\),\(k\),\(mod\),求随机排列在\(k\)层归并排序下逆序对的期望. 题解 考虑这\(k\)层归并会把序列分成若干个块. 这些块内的顺序是原序列的相对顺序,我们要把 ...
- HDU5800 To My Girlfriend 背包计数dp
分析:首先定义状态dp[i][j][s1][s2]代表前i个物品中,选若干个物品,总价值为j 其中s1个物品时必选,s2物品必不选的方案数 那么转移的时候可以考虑,第i个物品是可选可可不选的 dp[i ...
- CodeForces 176B Word Cut (计数DP)
Word Cut Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Submit St ...
- [DP之计数DP]
其实说实在 我在写这篇博客的时候 才刚刚草了一道这样类型的题 之前几乎没有接触过 接触过也是平时比赛的 没有系统的做过 可以说0基础 我所理解的计数dp就是想办法去达到它要的目的 而且一定要非常劲非常 ...
- HDU4815/计数DP
题目链接[http://acm.hdu.edu.cn/showproblem.php?pid=4815] 简单说一下题意: 有n道题,每到题答对得分为a[ i ],假如A不输给B的最小概率是P,那么A ...
- HDU 6377 度度熊看球赛 (计数DP)
度度熊看球赛 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
- 计数dp
计数dp 计数类的$dp$没做过几个,所以之前都放到"思维"标签下了,后来发现原来这属于一类问题啊...搬过来了. 管道取珠:https://www.lydsy.com/Judge ...
- [SDOI2010]地精部落[计数dp]
题意 求有多少长度为 \(n\) 的排列满足 \(a_1< a_2> a_3 < a_4 \cdots\) 或者 $a_1> a_2 < a_3 > a_4\cdo ...
- 【BZOJ】2111: [ZJOI2010]Perm 排列计数 计数DP+排列组合+lucas
[题目]BZOJ 2111 [题意]求有多少1~n的排列,满足\(A_i>A_{\frac{i}{2}}\),输出对p取模的结果.\(n \leq 10^6,p \leq 10^9\),p是素数 ...
- 【AtCoder】AGC022 F - Leftmost Ball 计数DP
[题目]F - Leftmost Ball [题意]给定n种颜色的球各k个,每次以任意顺序排列所有球并将每种颜色最左端的球染成颜色0,求有多少种不同的颜色排列.n,k<=2000. [算法]计数 ...
随机推荐
- JS的深浅复制,原来如此!
摘要:之所以会出现深浅拷贝的问题,实质上是由于JS对基本类型和引用类型的处理不同. 本文分享自华为云社区<js的深浅复制,一看就明白>,作者: 鑫2020. 浅复制的意思 浅复制是仅仅对数 ...
- HBuilderX获取iOS证书的打包步骤
简介: 目前app开发,很多企业都用H5框架来开发,而uniapp又是这些h5框架里面最成熟的,因此hbuilderx就成为了开发者的首选.然而,打包APP是需要证书的,那么这个证书又是如何获得呢? ...
- LAS Spark 在 TPC-DS 的优化揭秘
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 文章主要介绍了火山引擎湖仓一体分析服务 LAS Spark(下文以 LAS Spark 指代)在 TPC-DS 上 ...
- 火山引擎DataLeap的Data Catalog系统搜索实践 (上)
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 摘要 火山引擎大数据研发治理套件 DataLeap的Data Catalog系统通过汇总和组织各种元数据,解决了数 ...
- python指定大小文件生成
使用特定大小的随机数生成,使用随机数生成器生成特定大小的字节,并将其写入文件中 import os def generate_file(file_path, file_size_bytes): wit ...
- 【Django drf】序列化器总结
目录 序列化器字段 外键字段自定义序列化 在模型类中写方法 在序列化类中写方法 反序列化 外键字段反序列化保存 ModelSerializer使用总结 序列化器字段 序列化中的字段可以根据用途分为三种 ...
- ME21N 采购订单新增页签增强
1.实现效果 根据客制化需求,要在采购订单中新增大量字段,所以要在界面上添加一个单独的页签.效果如下: 2.增强实现 2.1.增强结构 因为是在抬头上边添加,所以增强CI_EKKODB结构 2.2.函 ...
- LT01 创建转储单
一.LT01创建转储单 采购订单--MIGO收货--虚拟仓位--LT01上架--实体仓位--LT01下架--虚拟仓位--MIGO发料--生产订单 二.参考代码 "-------------- ...
- PS组件相关BAPI
一.新增组件BAPI "-----------------------------------------@斌将军-------------------------------------- ...
- 库函数 | C++17 std::filesystem文件系统 用法指北
本文将针对常用的场景,对 std::filesystem 的使用逐一进行验证: 判断文件夹是否存在 创建单层目录 逐级创建多层目录 创建多级目录 当前文件路径 创建文件"from.dat&q ...