计数 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的for循环中出现异步函数,回调引用的循环值始终是最后的值
一.问题 今天工作中解决bug发现是由“for循环的异步函数,回调引用的循环值始终是最后的值”的现象导致的,如: for (var i = 0; i < files.length; i++) { ...
- 使用 SetParent 跨进程设置父子窗口时的一些问题(小心卡死)
原文:使用 SetParent 跨进程设置父子窗口时的一些问题(小心卡死) 在微软的官方文档中,说 SetParent 可以在进程内设置,也可以跨进程设置.当使用跨进程设置窗口的父子关系时,你需要注意 ...
- js 一些有意思的小Demo
- 如何在backoffice里创建Hybris image container以及分配给product
登录backoffice,在media container视图点击新建按钮: Catalog选择Product Catalog: 在Properties界面,可以选择media实例放入该contain ...
- IDEA远程连接和上传文件到服务器
公司电脑是win,所以远程控制服务器就不能用之前自己笔记本ubuntu自带的终端了. 后来在万能的群友的提醒下,IDEA本身就自带了远程功能,摸索了一下,使用IDEA连接服务器并且可以上传文件了. 这 ...
- CPN tools 帮助文档资料和实例
1.替代变迁 包含有替代变迁的页面叫做父页,当CPN网使用替代变迁的时候,替代变迁所表达的逻辑必须在某一个位置得到实现,实现替代变迁逻辑页面叫做子页或者子网. 将替代变迁相邻的库所叫做槽库所,也即是在 ...
- HTML&CSS基础-CSS的语法
HTML&CSS基础-CSS的语法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.dome.html源代码 <!DOCTYPE html> <html ...
- plsql查看是否锁表,锁模式等,以及解锁SQL
--工作中的点滴积累SELECT l.session_id sid, s.serial#, l.locked_mode 锁模式, l.oracle_username 登录用户, l.os_user_n ...
- 过采样中用到的SMOTE算法
平时很多分类问题都会面对样本不均衡的问题,很多算法在这种情况下分类效果都不够理想.类不平衡(class-imbalance)是指在训练分类器中所使用的训练集的类别分布不均.比如说一个二分类问题,100 ...
- k8s安装之etcd备份还原yaml
etcd备份还原方案,这种比较高级. 使用docker,自动化处理. 如果单节点备份,ETCD_ENDPOINTS一个即可. 如果多节点恢复,依次执行恢复脚本即可. apiVersion: batch ...