Codeforces 1096F(dp + 树状数组)
题意:
对于长度为$n$的排列,在已知一些位的前提下求逆序对的期望
思路:
将答案分为$3$部分
$1.$$-1$与$-1$之间对答案的贡献。由于逆序对考虑的是数字之间的大小关系,故假设$-1$的数量为$cnt$,可以等效成求长度为$cnt$的排列的逆序对期望。设$dp[i]$为长度为$i$的全排列的逆序对期望,有$dp[i]=dp[i-1]+$$\frac{i-1}{2}$,可以理解成在原$dp[i-1]$的基础上,数值$i$对每个长度为$i-1$的排列产生$\sum_{t=1}^{i-1}t$个逆序对,共有$(i-1)!$个排列,所以期望为$\frac{(i-1)!*i*(i-1)}{(2*i!)}$$=\frac{i-1}{2}$,移项后使用累加法可以求出通项为$dp[i]=$$\frac{i*(i-1)}{4}$。
$2.$非$-1$之间对答案的贡献。可以将出现概率看作$1$,所以贡献就是逆序对数量,用树状数组求。
$3.$$-1$与非$-1$之间的贡献。设共有$cnt$个$-1$,考虑每个$a[i]$$\neq$$-1$,设这个$a[i]$它前边$-1$的数量为$nop$,它大的未填的数的数量为$high[a[i]]$,那么$a[i]$对这部分答案的贡献为$\frac{nop*high[a[i]]*(cnt-1)!}{cnt!}$$=$$\frac{nop*high[a[i]]}{cnt}$。比$a[i]$小的数与$a[i]$后边的$-1$构成类似的关系。
代码:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <cassert>
#include <cstring>
#include <iostream>
#include <algorithm> #define IOS ios::sync_with_stdio(0),cin.tie(0);
#define DBG(x) cerr << #x << " = " << x << endl; #define PII pair<int,int>
#define FI first
#define SE second using namespace std; typedef long long LL;
typedef long double LD;
typedef unsigned long long ULL; const int inf = 0x3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;
const double pi = acos(-1.0); void file(){
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
} namespace BakuretsuMahou{ const int N = 2e5 + 5;
const int inv2 = (mod + 1) / 2; int n, a[N], vis[N];
int high[N], low[N];
int pre[N], cnt;
LL ans, fac[N]; LL add(LL a, LL b){
return (a+b)%mod;
} LL mul(LL a, LL b){
return (a*b)%mod;
} struct BIT{ int c[N]; int lowbit(int x){
return (x)&(-x);
} void update(int x, int y){
while(x <= n){
c[x] += y;
x += lowbit(x);
}
} LL query(int x){
LL res = 0;
while(x >= 1){
res += c[x];
x -= lowbit(x);
}
return res;
}
}tree; LL qpow(LL a, LL b, LL p){
LL res = 1;
while(b){
if(b&1)res = mul(res, a);
a = mul(a, a);
b >>= 1;
}
return res;
} LL Fermat(LL a, LL p){
return qpow(a, p - 2, p);
} LL dp(LL x){
return mul(mul(x, x - 1), Fermat(4, mod));
} void init(){
fac[0] = 1;
for(int i = 1; i < N; i++){
fac[i] = mul(fac[i - 1], i);
}
} void Explosion(){
init();
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
if(a[i] != -1){
vis[a[i]] = 1;
ans = add(ans, i - 1 - cnt - tree.query(a[i]));
tree.update(a[i], 1);
}else cnt++, pre[i]++;
pre[i] += pre[i - 1];
}
ans = add(ans, dp(cnt));
LL inv = Fermat(cnt, mod);
for(int i = 2; i <= n; i++)low[i] = low[i - 1] + (vis[i - 1] ^ 1);
for(int i = n - 1; i >= 1; i--)high[i] = high[i + 1] + (vis[i + 1] ^ 1);
for(int i = 1; i <= n; i++){
if(a[i] != -1){
LL nop = pre[i], nos = pre[n] - pre[i];
ans = add(ans, mul(mul(nos, low[a[i]]), inv));
ans = add(ans, mul(mul(nop, high[a[i]]), inv));
}
}
printf("%I64d\n", ans);
}
} int main(){
//IOS
//file();
BakuretsuMahou::Explosion();
return 0;
}
Codeforces 1096F(dp + 树状数组)的更多相关文章
- Codeforces 1111E DP + 树状数组 + LCA + dfs序
题意:给你一颗树,有q次询问,每次询问给你若干个点,这些点可以最多分出m组,每组要满足两个条件:1:每组至少一个点,2:组内的点不能是组内其它点的祖先,问这样的分组能有多少个? 思路:https:// ...
- 树形DP+树状数组 HDU 5877 Weak Pair
//树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...
- bzoj 1264 [AHOI2006]基因匹配Match(DP+树状数组)
1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 793 Solved: 503[Submit][S ...
- 【bzoj2274】[Usaco2011 Feb]Generic Cow Protests dp+树状数组
题目描述 Farmer John's N (1 <= N <= 100,000) cows are lined up in a row andnumbered 1..N. The cows ...
- 奶牛抗议 DP 树状数组
奶牛抗议 DP 树状数组 USACO的题太猛了 容易想到\(DP\),设\(f[i]\)表示为在第\(i\)位时方案数,转移方程: \[ f[i]=\sum f[j]\;(j< i,sum[i] ...
- codeforces 597C (树状数组+DP)
题目链接:http://codeforces.com/contest/597/problem/C 思路:dp[i][j]表示长度为i,以j结尾的上升子序列,则有dp[i][j]= ∑dp[i-1][k ...
- Codeforces 597C. Subsequences (树状数组+dp)
题目链接:http://codeforces.com/contest/597/problem/C 给你n和数(1~n各不同),问你长为k+1的上升自序列有多少. dp[i][j] 表示末尾数字为i 长 ...
- CodeForces - 597C Subsequences 【DP + 树状数组】
题目链接 http://codeforces.com/problemset/problem/597/C 题意 给出一个n 一个 k 求 n 个数中 长度为k的上升子序列 有多少个 思路 刚开始就是想用 ...
- codeforces 597C C. Subsequences(dp+树状数组)
题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standar ...
随机推荐
- Git的可视化工具SourceTree管理代码 SourceTree的使用
出处:https://blog.csdn.net/android_zhengyongbo/article/details/72885860 其他参考资料https://www.cnblogs.com/ ...
- supervisord支持扩展(xml RPC API & Third Party Applications and Libraries)
XML-RPC API Documentation http://www.supervisord.org/api.html Third Party Applications and Libraries ...
- OpenCV 与 OpenGL 的关系是什么?
OpenCV是 Open Source Computer Vision LibraryOpenGL是 Open Graphics LibraryOpenCV主要是提供图像处理和视频处理的基础算法库,还 ...
- JS检测浏览器是否最大化
function isFullScreen (){ if( window.outerHeight === screen.availHeight ){ i ...
- python小白——进阶之路——day4天-———流程控制while if循环
# ### 代码块: 以冒号作为开始,用缩进来划分作用域,这个整体叫做代码块 if 5 == 5: print(1) print(2) # 注意点: 要么全部使用4个空格,要么全部使用1个缩进 ,这样 ...
- yafu安装使用方法以及mismatched parens解决方法
yafu用于自动整数因式分解,在RSA中,当p.q的取值差异过大或过于相近的时候,使用yafu可以快速的把n值分解出p.q值,原理是使用Fermat方法与Pollard rho方法等. 再摘录官方的一 ...
- 用Eclipse中的git提交代码流程
有更新有提交 Commit到本地,pull,然后再push 提交 Commit到本地 或者直接commit and Push 更新 先对比然后pull或者右键项目直接pull 有冲突时 有冲突的时候优 ...
- MyBatis:二级缓存原理分析
MyBatis从入门到放弃七:二级缓存原理分析 前言 说起mybatis的一级缓存和二级缓存我特意问了几个身边的朋友他们平时会不会用,结果没有一个人平时业务场景中用. 好吧,那我暂且用来学习源码吧.一 ...
- 电脑重装系统后如何恢复 Mysql 数据库
电脑重装系统后如何恢复 Mysql 数据库 一.[设置mysql的path] 比如:我的mysql在:D:\DataBase\mysql-5.7.13-winx64,可以在环境变量中重新新建一个环境变 ...
- Scrapy-redis 组件
scrapy-redis 简介 scrapy-redis是scrapy框架基于redis数据库的组件,用于scrapy项目的分布式开发和部署. 特征 分布式爬取 可以启动多个spider工程,相互之间 ...