CF1081G Mergesort Strikes Back
Posted miracevin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1081G Mergesort Strikes Back相关的知识,希望对你有一定的参考价值。
CF1081G Mergesort Strikes Back
概率好题
之前做过一些考察排序本质的题目
如:[USACO18OPEN]Out of Sorts G 冒泡排序理解之一
混合快排:[USACO18OPEN]Out of Sorts P 冒泡排序理解之二
本题考察归并排序。
考虑所有排列中,两个位置贡献逆序对的概率。
由于底层是原序列,从底层若干个序列考虑。
序列内部,序列之间两类逆序对。
每个序列长度为l,内部方案数l*(l-1)/4(两对1/2概率贡献,归并中相对顺序不变,直接加到答案)
序列之间?
归并有一种弹栈、单调的感觉
可以把序列分成若干块,每块的起点都是前缀最大值。
且这些块起点放入,整个块顺着就放完了。
且这些块相对顺序不变,到最后也还是完整的块。
对于两个序列第i和第j个位置有贡献的概率?
考虑这i+j个元素,i、j二者之一如果是最大值,那么一定不会有贡献
否则有1/2概率有贡献。即:(i+j-2)/(i+j)*1/2=1/2-1/(i+j)
枚举i,处理倒数的前缀和
序列不同的长度只有2种,做一下就好了。
#include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^‘0‘) #define pb push_back #define solid const auto & #define enter cout<<endl #define pii pair<int,int> using namespace std; typedef long long ll; template<class T>il void rd(T &x) char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch==‘-‘)&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x); template<class T>il void output(T x)if(x/10)output(x/10);putchar(x%10+‘0‘); template<class T>il void ot(T x)if(x<0) putchar(‘-‘),x=-x;output(x);putchar(‘ ‘); template<class T>il void prt(T a[],int st,int nd)for(reg i=st;i<=nd;++i) ot(a[i]);putchar(‘\\n‘); namespace Modulo int mod; il int ad(int x,int y)return x+y>=mod?x+y-mod:x+y; il int sub(int x,int y)return ad(x,mod-y); il int mul(int x,int y)return (ll)x*y%mod; il void inc(int &x,int y)x=ad(x,y); il void inc2(int &x,int y)x=mul(x,y); il int qm(int x,int y=mod-2)int ret=1;while(y)if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;return ret; template<class ...Args>il int ad(const int a,const int b,const Args &...args) return ad(ad(a,b),args...); template<class ...Args>il int mul(const int a,const int b,const Args &...args) return mul(mul(a,b),args...); using namespace Modulo; namespace Miracle const int N=1e5+5; int n,k; int iv[N],s[N]; int l1,l2,c1,c2; void divi(int l,int r,int d) if(d==k||l==r) if(!l1) l1=r-l+1;++c1; else if(r-l+1==l1) ++c1; else if(!l2) l2=r-l+1,++c2; else ++c2; return; int mid=(l+r)>>1; divi(l,mid,d+1);divi(mid+1,r,d+1); int calc(int l1,int l2) if(!l1||!l2) return 0; int ret=mul(l1,l2,qm(2)); for(reg i=1;i<=l1;++i) ret=sub(ret,sub(s[i+l2],s[i])); return ret; int main() rd(n);rd(k);rd(mod); iv[1]=1; for(reg i=2;i<=n;++i) iv[i]=mul(mod-mod/i,iv[mod%i]); for(reg i=1;i<=n;++i) s[i]=ad(s[i-1],iv[i]); divi(1,n,1); int ans=ad(mul(c1,l1,(l1-1),qm(4)),mul(c2,l2,(l2-1),qm(4))); inc(ans,mul(c1,c1-1,qm(2),calc(l1,l1))); inc(ans,mul(c2,c2-1,qm(2),calc(l2,l2))); inc(ans,mul(c1,c2,calc(l1,l2))); ot(ans); return 0; signed main() Miracle::main(); return 0; /* Author: *Miracle* */
以上是关于CF1081G Mergesort Strikes Back的主要内容,如果未能解决你的问题,请参考以下文章