计数 luogu 4223 期望逆序对
https://www.luogu.org/problemnew/show/P4223
期望乘以\(\binom {n}{2}^k\)变成了计数问题
我们考虑每一组数\((A, B)\)产生的贡献CCCCCACCCCBCCCC
分7组考虑\((A, B)\)在\(k\)次操作之后去哪里了
\((A, B)\; (A, C)\;(B,A)\;(B,C)\;(C,A)\;(C,B)\;(C,C)\)
可以列出一个\(7 \times 7\)的矩阵表
矩阵快速幂后表示转移\(k\)次之后的系数(有点恶心
有一个结论就是CCCACCCBCCC
对于比如\((A, C)\)这个状态
\(B\)到达\(A\)左边和到达\(B\)右边的方案数是和\(C\)的个数成正比的
数学归纳法可证
因此推出式子可以发现\(i\)对\(j>i\)的贡献是一样的
树状数组维护即可
复杂度\(\mathcal O(n\log n)\)
#include <bits/stdc++.h>
#define int long long
#define fo(i, n) for(int i = 1; i <= (n); i ++)
#define out(x) cerr << #x << " = " << x << "\n"
#define type(x) __typeof((x).begin())
#define foreach(it, x) for(type(x) it = (x).begin(); it != (x).end(); ++ it)
using namespace std;
// by piano
template<typename tp> inline void read(tp &x) {
x = 0;char c = getchar(); bool f = 0;
for(; c < '0' || c > '9'; f |= (c == '-'), c = getchar());
for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
if(f) x = -x;
}
const int N = 5e5 + 233;
namespace {
const int mo = 1e9 + 7;
inline int add(int u, int v) {
if((u += v) >= mo) u -= mo;
return u;
}
inline int sub(int u, int v) {
if((u -= v) < 0) u += mo;
return u;
}
inline int mul(int u, int v) {
return u * v % mo;
}
inline int pw(int a, int k, int mo) {
int ans = 1;
for(; k; k >>= 1, a = mul(a, a))
if(k & 1) ans = mul(ans, a);
return ans;
}
}
struct Mar {
int m[7][7];
Mar() {
memset(m, 0, sizeof m);
}
inline void E(void) {
for(int i = 0; i < 7; i ++)
m[i][i] = 1;
}
}f, ans;
int a[N];
int cnt = 0, n, K;
Mar operator * (Mar a, Mar b) {
Mar c;
for(int i = 0; i < 7; i ++)
for(int j = 0; j < 7; j ++) {
int t = 0;
for(int k = 0; k < 7; k ++)
t = add(t, mul(a.m[i][k], b.m[k][j]));
c.m[i][j] = t;
}
return c;
}
inline void I(int a, int b, int c, int d, int e, int g, int h) {
f.m[cnt][0] = a; f.m[cnt][1] = b; f.m[cnt][2] = c;
f.m[cnt][3] = d; f.m[cnt][4] = e; f.m[cnt][5] = g;
f.m[cnt][6] = h;
cnt ++;
}
inline void Matrix_Init(void) {
int t = (n - 2) * (n - 3) / 2 % mo;
I(t, n - 2, 1, 0, 0, n - 2, 0);
I(1, t + n - 3, 0, 1, 1, 0, n - 3);
I(1, 0, t, n - 2, n - 2, 0, 0);
I(0, 1, 1, t + n - 3, 0, 1, n - 3);
I(0, 1, 1, 0, t + n - 3, 1, n - 3);
I(1, 0, 0, 1, 1, t + n - 3, n - 3);
I(0, 1, 0, 1, 1, 1, t + 2 * (n - 4) + 1);
}
inline Mar mf(Mar a, int k) {
Mar ans; ans.E();
for(; k; k >>= 1, a = a * a)
if(k & 1) ans = ans * a;
return ans;
}
struct Bit {
int tr[N], n;
inline void init(void) {
memset(tr, 0, sizeof tr);
n = ::n;
}
inline void A(int u, int val) {
for(; u <= n; u += u & -u)
tr[u] = add(tr[u], val);
}
inline int Q(int u) {
int ans = 0;
for(; u >= 1; u -= u & -u)
ans = add(ans, tr[u]);
return ans;
}
}x, y, z;
inline void doit(void) {
x.init(); y.init(); z.init();
int p = pw(n - 2, mo - 2, mo);
int inv2 = pw(2, mo - 2, mo);
int res = mul(n * (n - 1) / 2 % mo, ans.m[0][6]);
res = mul(res, inv2);
for(int j = 1; j <= n; j ++) {
int t;
int sm = x.Q(a[j] - 1);
int la = j - 1 - sm;
int p1 = add(mul(ans.m[0][3], mul(n - j, p)), mul(ans.m[0][5], mul(j - 2, p)));
int p2 = add(mul(ans.m[0][3], mul(j - 2, p)), mul(ans.m[0][5], mul(n - j, p)));
res = add(res, add(mul(la, p1), mul(sm, p2)));
res = add(res, add(mul(la, ans.m[0][0]),
mul(sm, ans.m[0][2])));
res = add(res, add(sub(y.Q(n), y.Q(a[j])), z.Q(a[j] - 1)));
x.A(a[j], 1);
t = add(mul(ans.m[0][1], mul(n - j - 1, p)),
mul(ans.m[0][4], mul(j - 1, p)));
y.A(a[j], t);
t = add(mul(ans.m[0][1], mul(j - 1, p)),
mul(ans.m[0][4], mul(n - j - 1, p)));
z.A(a[j], t);
}
cout << res << "\n";
}
main(void) {
read(n); read(K);
fo(i, n) read(a[i]);
Matrix_Init();
ans = mf(f, K);
doit();
}
计数 luogu 4223 期望逆序对的更多相关文章
- Luogu P4280 [AHOI2008]逆序对
题目描述 甩个链接就走 题解 先预处理出每个位置上分别填上 1~k 的数的逆序对的数量的前缀和与后缀和 (不用管原来有值的,统计时不计入答案就行了) (有点绕,看代码应该能懂) 然后枚举每个 -1 的 ...
- BZOJ5058 期望逆序对 【矩乘 + 组合数学 + 树状数组】
题目链接 BZOJ5058 题解 可以发现任意两个位置\(A,B\)最终位置关系的概率是相等的 如果数列是这样: CCCCACCCCBCCCC 那么最终有\(7\)种位置关系 \((A,B)\) \( ...
- Wannafly Camp 2020 Day 1A 期望逆序对 - 概率期望
分类讨论即可 #include <bits/stdc++.h> using namespace std; #define int long long const int N = 5005; ...
- luogu P1966 火柴排队 (逆序对)
luogu P1966 火柴排队 题目链接:https://www.luogu.org/problemnew/show/P1966 显然贪心的想,排名一样的数相减是最优的. 证明也很简单. 此处就不证 ...
- [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)
[BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...
- luogu 1521-求逆序对
题意: 逆序对指在一个序列中ai>aj && i < j,也就是一前一后两个数,当大的在前面的时候即算一对. 题目求在一个由1-n组成的序列中逆序对为k的序列的个数. 出题 ...
- luogu 1966 火柴排队 离散化+逆序对
题意:找到最小改变对数使a数组的第i大和b数组的第i大相等 则先将a,b,数组编号再排序,则数组显示的就是排名第i的数的编号 再关键一步:c[a[i].id]=b[i].id 实质上就是新建一个数组, ...
- 【Luogu】P3157动态逆序对(树状数组套主席树)
题目链接 md第一道在NOILinux 下用vim做的紫题.由于我对这个操作系统不是很熟悉,似乎有什么地方搞错了,md调死.(我还打了两遍代码,调了两个小时) 但是这道题并不难,就是树状数组套上主席树 ...
- [LUOGU] P1908 逆序对
题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为"逆序对"的 ...
随机推荐
- java之单元测试
这篇主要简单讲下java的单元测试 目录结构如下: 如图,其中1是需要被测试的功能:2是测试模块:3是单元测试需要的引入包: 1. 功能模块1中 Calculator 的代码: package cn. ...
- C# vb .net实现高斯模糊
在.net中,如何简单快捷地实现Photoshop滤镜组中的高斯模糊效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第 ...
- 视频质量评估 之 VMAF
VMAF 方法: 基本想法: 面对不同特征的源内容.失真类型,以及扭曲程度,每个基本指标各有优劣.通过使用机器学习算法(支持向量机(Support Vector Machine,SVM)回归因子)将基 ...
- OpenJML入门
目录 OpenJML 获取 下载 使用 Linux Windows Parsing and Type-checking Extended Static Checking Runtime Asserti ...
- springboot activiti 工作流版本 集成代码生成器 shiro 安全框架
官网:www.fhadmin.org 工作流模块---------------------------------------------------------------------------- ...
- JavaScript内置一些方法的实现原理--new关键字,call/apply/bind方法--实现
先学习下new操作符吧 new关键字调用函数的心路历程: 1.创建一个新对象 2.将函数的作用域赋给新对象(this就指向这个对象) 3.执行函数中的代码 4.返回这个对象 根据这个的思路,来实现一个 ...
- 过滤器+用session验证是否登陆过
过滤器: public class MyActionFilter : ActionFilterAttribute//继承ActionFilterAttribute类 { public override ...
- Linux之nginx负载均衡
Nginx负载均衡概述 Web服务器,直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我使用多台WEB服务器组成集群,前端使用Nginx负载均衡,将请求分散的打到我们的后端服务器集群中,实现 ...
- atoi()和itoa()函数详解以及C语言实现
atoi()函数 atoi()原型: int atoi(const char *str ); 函数功能:把字符串转换成整型数. 参数str:要进行转换的字符串 返回值:每个函数返回 int 值,此值 ...
- Centos 7.6 双网卡绑定实现高可用
Centos 7.6 双网卡绑定实现高可用 作者:尹正杰 版权声明:原创作品, 谢绝转载!否则将追究法律责任. 一.Bond模式概述 当linux系统上有多个单独网卡,又想充分利用这些网卡,同时对外提 ...