[CSP-S模拟测试]:Cicada与排序(概率DP)
题目传送门(内部题93)
输入格式
第一行一个整数$n$,代表数列的长度。
接下来一行$n$个数$a_i$,用空格分隔开。
输出格式
输出一行$n$个数,表示原数列上这个位置在执行后的期望位置,注意输出的是期望值在$\mod 998244353$下的结果。
数据范围与提示
$n\leqslant 500,1\leqslant a_i\leqslant 10^3$

题解
考虑$DP$,设$dp[i][j][k]$表示在第$i$层下原来的$j$在现在排名为$k$的概率,发现还是不好转移。
再设$g[i][j]$表示在归并排序过程中两个指针分别指向$i,j$的概率,先求出$g$数组,然后直接转移即可。
证明一下时间复杂度,发现每层实际上就是一个卷积,那么复杂度为$T(n)=n^2+2T(\frac{n}{2})$,根据主定理,每层的时间复杂度为$T(n)=n^2$。所以处理单个数的时间复杂度为$\Theta(n^2)$,因为要处理每个数,于是时间复杂度为$\Theta(n^3)$。
时间复杂度:$\Theta(n^3)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
const int two=499122177;
int n;
int a[501];
long long f[501][501][501],g[501][501],ans;
void merge_sort(int x,int l,int r)
{
if(l==r){f[x][l][l]=1;return;}
int mid=(l+r)>>1;
merge_sort(x+1,l,mid);
merge_sort(x+1,mid+1,r);
memset(g,0,sizeof(g));
g[0][0]=1;
for(int i=0;i<=mid-l+1;i++)
for(int j=0;j<=r-mid;j++)
{
if(i==mid-l+1)g[i][j+1]=(g[i][j+1]+g[i][j])%mod;
else if(j==r-mid)g[i+1][j]=(g[i+1][j]+g[i][j])%mod;
else if(a[i+l]<a[j+mid+1])g[i+1][j]=(g[i+1][j]+g[i][j])%mod;
else if(a[i+l]>a[j+mid+1])g[i][j+1]=(g[i][j+1]+g[i][j])%mod;
else
{
g[i+1][j]=(g[i+1][j]+g[i][j]*two%mod)%mod;
g[i][j+1]=(g[i][j+1]+g[i][j]*two%mod)%mod;
}
}
for(int i=l;i<=r;i++)
for(int j=0;j<=mid-l+1;j++)
for(int k=0;k<=r-mid;k++)
{
if(j==mid-l+1&&k==r-mid)continue;
if(j==mid-l+1)f[x][i][j+k+l]=(f[x][i][j+k+l]+f[x+1][i][k+mid+1]*g[j][k]%mod)%mod;
else if(k==r-mid)f[x][i][j+k+l]=(f[x][i][j+k+l]+f[x+1][i][j+l]*g[j][k]%mod)%mod;
else if(a[j+l]<a[k+mid+1])f[x][i][j+k+l]=(f[x][i][j+k+l]+f[x+1][i][j+l]*g[j][k]%mod)%mod;
else if(a[j+l]>a[k+mid+1])f[x][i][j+k+l]=(f[x][i][j+k+l]+f[x+1][i][k+mid+1]*g[j][k]%mod)%mod;
else
{
f[x][i][j+k+l]=(f[x][i][j+k+l]+f[x+1][i][k+mid+1]*g[j][k]%mod*two%mod)%mod;
f[x][i][j+k+l]=(f[x][i][j+k+l]+f[x+1][i][j+l]*g[j][k]%mod*two%mod)%mod;
}
}
sort(a+l,a+r+1);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
merge_sort(1,1,n);
for(int i=1;i<=n;i++)
{
ans=0;
for(int j=1;j<=n;j++)
ans=(ans+f[1][i][j]*j)%mod;
printf("%lld ",ans);
}
return 0;
}
rp++
[CSP-S模拟测试]:Cicada与排序(概率DP)的更多相关文章
- [CSP-S模拟测试]:糊涂图(概率DP)
题目传送门(内部题76) 输入格式 第一行输入三个空格隔开的整数$n,m,s$表示随机加一条边之前的糊涂图的点数,边数,以及起点的编号. 接下来$m$行,每行两个空格隔开的整数$a,b$表示从$a$到 ...
- [CSP-S模拟测试]:抽卡(概率DP)
题目描述 水上由岐最近在肝手游,游戏里有一个氪金抽卡的活动.有$n$种卡,每种卡有 3 种颜色.每次抽卡可能什么也抽不到,也可能抽到一张卡.每氪金一次可以连抽 m 次卡,其中前$m−1$次抽到第$i$ ...
- 「10.28」Dove 打扑克(链表)·Cicada 与排序(概率)·Cicada 拿衣服(各种数据结构)
A. Dove 打扑克 考场思考半天线段树树状数组,没有什么想法 打完暴力后突然想到此题用链表实现会很快. 因为只有$n$堆,所以设最多有$x$个不同的堆数,那么$x\times (x-1)/2==n ...
- 20190716NOIP模拟赛T1 礼物(概率dp+状压)
题目描述 夏川的生日就要到了.作为夏川形式上的男朋友,季堂打算给夏川买一些生 日礼物. 商店里一共有种礼物.夏川每得到一种礼物,就会获得相应喜悦值Wi(每种 礼物的喜悦值不能重复获得). 每次,店员会 ...
- [CSP-S模拟测试]:Cicada拿衣服(暴力+乱搞)
题目传送门(内部题94) 输入格式 第一行两个整数$n,k$,代表衣服的数量和阈值. 接下来一行$n$个数,第$i$个数$a_i$表示每件衣服的愉悦值. 输出格式 输出一行$n$个数,第$i$个数为$ ...
- [CSP-S模拟测试]:城市游戏(图论+DP)
题目传送门(内部题109) 输入格式 第一行,两个整数$n,m$. 接下来$m$行,每行三个整数$u,v,l$,描述了一条道路连接的两个路口的编号以及道路的长度. 输出格式 输出一行一个整数,为所求的 ...
- [CSP-S模拟测试]:简单的期望(DP)
题目描述 从前有个变量$x$,它的初始值已给出. 你会依次执行$n$次操作,每次操作有$p\%$的概率令$x=x\times 2$,$(100−p)\%$的概率令$x=x+1$. 假设最后得到的值为$ ...
- [CSP-S模拟测试]:二叉搜索树(DP+贪心)
题目传送门(内部题99) 输入格式 第一行一个整数$n$,第二行$n$个整数$x_1\sim x_n$. 输出格式 一行一个整数表示答案. 样例 样例输入: 58 2 1 4 3 样例输出: 数据范围 ...
- [CSP-S模拟测试]:装饰(状压DP)
题目传送门(内部题114) 输入格式 第一行一个正整数$n$. 接下来一行$n-1$个正整数,第$i$个数为$f_{i+1}$. 接下来一行$n$个数,若第$i$个数为$0$则表示林先森希望$i$号点 ...
随机推荐
- 洛谷 P1306 斐波那契公约数 题解
题面 结论:gcd(F[n],F[m])=F[gcd(n,m)]; F[n]=a和F[n+1]=b F[n+2]=a+b,F[n+3]=a+2b,…F[m]=F[m?n?1]a+F[m?n]b F[n ...
- C语言--浮点数
在程序中使用浮点数 -- 浮点数的精确性有限 -- 在从c语言中float类型的精确度只到小数点的7位 -- 浮点数只能在一定范围内去相信它 -- 在有精确度高的要求下不要使用浮点数(在算钱的时候,误 ...
- Layui关闭弹出层并刷新父窗口
先确保已经引入layui和jquery 再确保初始化layer弹出层 <script> layui.use(['form', 'layer'], function() { var form ...
- Nginx + Tomcat动静分离 (转)
什么是动静分离 为了提高网站的响应速度,减轻程序服务器(Tomcat,Jboss等)的负载,对于静态资源比如图片,js,css等文件,我们可以在反向代理服务器中进行缓存,这样浏览器在请求一个静态资源时 ...
- Codeforces893F_Subtree Minimum Query
题意 给定一棵树和根,每个点有点权,强制在线询问\(x\)子树里离\(x\)距离不超过\(k\)的最小点权. 分析 权值线段树合并的套路题,dfs,以深度作为下标,点权作为值,对每个点建立一颗权值线段 ...
- 使用 tablib 来自动化管理测试用例,其他的工具都不用学了
你在学习 python 自动化测试吗?听过 requests 库吗?tablib 是 requests 库作者常年维护的一个可以操作 Excel 等多种文件格式,将他们变成一种通用数据集的第三方库. ...
- java复习(3)继承下
一.抽象类 ------------------------------------- 1.抽象定义概述:抽象类时从多个事物中奖共性的,本质的内容抽取出来 例如:狼和狗共性都是犬科,犬科就是抽象出来的 ...
- python实现加密的方式总结
python实现加密的方式总结 原文地址 目录 基础知识扫盲 Base64 MD5 DES 3DES AES RSA 基础知识扫盲 对称加密 对称密钥加密 , 又叫私钥加密.即信息发送的方和接受方用一 ...
- 异步分布式队列Celery
异步分布式队列Celery 转载地址 Celery 是什么? 官网 Celery 是一个由 Python 编写的简单.灵活.可靠的用来处理大量信息的分布式系统,它同时提供操作和维护分布式系统所需的工具 ...
- Maven项目构建利器05——Maven的生命周期
Maven各个构建环节执行的顺序: 不能打乱顺序, 必须按照既定的正确顺序(编译,测试.打包.部署)来执行Maven的核心程序中定义了抽象的生命周期, 生命周期中各个阶段的具体任务是由插件来完成的,可 ...