计数 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老猫查阅到一个人类称之为"逆序对"的 ...
随机推荐
- Js学习04--对象
1.如何辨别js中的对象 除了五种基本的数据类型,其他的都是对象.万物皆对象. 2.Js中对象的分类 1)内建对象 由ES标准定义的对象,在任何的ES实现中都可以使用. eg:String.Numbe ...
- 3.01定义常量之define
[注:本程序验证是使用vs2013版] #include <stdio.h> #include <stdlib.h> #include <string.h> #pr ...
- 1.Rabbitmq学习记录《本质介绍,协议AMQP分析》
1.RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现. RabbitMQ的优势-: 除了Qpid,RabbitMQ是唯一一个实现了AMQP ...
- python基础_MySQL的bigint类型
bigint支持的数字的大小范围为:19位,存电话号码.有符号范围:-9223372036854775808 到 9223372036854775807 int支持的数字范围为:10位,有符号范围:- ...
- Codeforces Round #570 Div. 3
A:暴力从小到大枚举判断. #include<bits/stdc++.h> using namespace std; #define ll long long #define inf 10 ...
- Docker安装带中文全文搜索插件zhparser的Postgresql数据库
上一篇讲了在已经安装了PG数据库的情况下,安装全文搜索插件zhparser遇到的问题.在一个全新的环境中安装带有全文搜索插件zhparser的PG数据库,可以使用已经做好的Docker镜像,在安装的过 ...
- c# 获取网页的爬虫程序
转载于:https://www.cnblogs.com/wzk153/p/9145684.html HtmlAgilityPack相关详解: https://www.cnblogs.com/asxin ...
- C#程序结构(学习笔记01)
C#程序结构 [原文参考官方教程] https://docs.microsoft.com/zh-cn/dotnet/csharp/tour-of-csharp/program-structure C# ...
- Vue路由传参的几种方式
原 Vue路由传参的几种方式 2018年07月28日 23:52:40 广积粮缓称王 阅读数 12613 前言:顾名思义,vue路由传参是指嵌套路由时父路由向子路由传递参数,否则操作无效.传参方式 ...
- C#入门概述
ASP.NET 则是一种技术. Main方法 代码编写规范 命名规范