[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$号点 ...
随机推荐
- [gym101981M][2018ICPC南京M题]Mediocre String Problem
题目链接 题目大意是问在$S$串中找区间$[i,j]$,在$T$串中找位置$k$,使得$S[i,j]$和$T[1,k]$可以组成回文串,并且$j-i+1>k$,求这样的三元组$(i,j,k)$的 ...
- 深入理解let和var的区别
首先我们应该知道js引擎在读取js代码时会进行两个步骤: 第一个步骤是解释. 第二个步骤是执行. 所谓解释就是会先通篇扫描所有的Js代码,然后把所有声明提升到顶端,第二步是执行,执行就是操作一类的. ...
- vim 文本编辑器
vim 文件名:命令模式 i 编辑模式 :输入模式 vim +n 文件名:打开文件,将光标置于第N行首部 命令模式进入输入模式进行编辑: i 当前光标位置插入文本 I 在当前行行首插入文本 o 在光标 ...
- Action获取请求参数的3中方式
方式一:Action本身作为Model对象,通过属性注入(Setter)方法讲参数数据封装到Action中 具体为:在Action中,提供和参数名相同的几个属性,并为其提供set方法,那么,该参数会被 ...
- Nginx优化_访问并发量(进程可以打开的最大文件数量)
如果客户端访问服务器提示“Too many open files”如何解决? [root@proxy ~]# ab -n 2000 -c 2000 http://192.168.1.100/ # ...
- Linux部署Redis及PHP-redis扩展
Redis是一个key-value存储系统,属于我们常说的NoSQL.它遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.它常用在缓存.队列.P ...
- [StructLayout(LayoutKind.Sequential) ] 是什么意思
首先介绍一下 结构体和类的区别 :类是按引用传递 结构体是按值传递进入正题:结构体是由若干成员组成的.布局有两种1.Sequential,顺序布局,比如struct S1{int a;int b;}那 ...
- 深入理解docker
注意这是一篇笔记整理,来源是一篇公众号,https://mp.weixin.qq.com/s/vS-Dp31T19Rk_tQj2GzmCQ 为了自己更好的查看和理解,涉及到侵权联系删! 目录: Ima ...
- SCC统计
Kosoraju SCC总数及记录SCC所需要的最少边情况 #include<cstdio> ; ; ][N], nxt[][N], v[][N], ed, q[N], t, vis[N] ...
- java课堂测试2(两种方式)
实验源代码 这是不使用数组形式的源代码 /* 2017/10/10 王翌淞 课堂测试2 */import java.util.Scanner; public class Number { public ...