计数 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老猫查阅到一个人类称之为"逆序对"的 ...
随机推荐
- python基础_mysql建表、编辑、删除、查询、更新
1.建一张学生表 包含(id,name,age,sex)2.增加四条数据3.查询表中sex为男的数据4.删除id =3的数据,5.将sex为女的,修改为男 create: CREATE TABLE d ...
- Java 哈希表
public int firstUniqChar(String s){ int[] freq=new int[26]; for(int i=0;i<s.length();i++){ freq[s ...
- 如何更精准地设置 C# / .NET Core 项目的输出路径?(包括添加和删除各种前后缀)
原文:如何更精准地设置 C# / .NET Core 项目的输出路径?(包括添加和删除各种前后缀) 我们都知道可以通过在 Visual Studio 中设置输出路径(OutputPath)来更改项目输 ...
- rabbitmq保证数据不丢失方案
rabbitmq如何保证消息的可靠性 1.保证消息不丢失 1.1.开启事务(不推荐) 1.2.开启confirm(推荐) 1.3.开启RabbitMQ的持久化(交换机.队列.消息) 1.4.关闭Rab ...
- Swift之xib模块化设计
一.解决问题 Xib/Storybarod可以方便.可视化的设置约束,在开发中也越来越重要.由于Xib不能组件化,使得封装.重用都变得不可行.本文将介绍一种解决方案,来实现Xib组件化. 二.模型块原 ...
- 解决internal/modules/cjs/loader.js:638 throw err; ^ Error: Cannot find module 'resolve'
internal/modules/cjs/loader.js:638 throw err; ^ Error: Cannot find module 'resolve' 根据提示可以知道有依赖没有安装完 ...
- JAVA基础之ServletContext应用
创建一个登陆的界面,并且统计次数! 导入jar包; 1. driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/java0603?u ...
- mysql 数据库 规范
目录 mysql 数据库 规范 基础规范 命名规范 表设计规范 字段设计规范 索引设计规范 SQL编写规范 行为规范 mysql 数据库 规范 基础规范 必须使用InnoDB存储引擎 解读:支持事务. ...
- Redis 学习-Redis 的其他功能
一.慢查询 找到 系统中瓶颈的命令 1. 客户端请求的生命周期: ①. 慢查询通常发生在第三阶段. ②. 客户端超时不一定是慢查询,但慢查询是客户端超时的一个可能因素. 2. 相关配置 慢查询命令会存 ...
- 微信小程序之生成图片分享 二维码分享 canvas绘制
如果本文对你有用,请爱心点个赞,提高排名,帮助更多的人.谢谢大家!❤ 如果解决不了,可以在文末进群交流. 添加画布 首先,在小程序里进行绘图操作需要用到<canvas>组件,步骤大致分为以 ...