AT2366-[AGC012F]Prefix Median【dp】

1|0正题

题目链接:https://www.luogu.com.cn/problem/AT2366


1|1题目大意

有一个长度为2n1的序列a,你可以将其重新排列,定义bia12i1的中位数。

询问有多少种不同的可能的b序列。

1n50


1|2解题思路

先假设a中所有数字都不同,我们去考虑一下b的限制。

相当于我们每次在ai中加入两个数字x,y,然后如果x,y都小于最后一个b则新的b取它在a中的前驱,如果都大于则取后继,如果一大一小则不动。

基于这个限制我们得到的条件是每次bi加入数字之后的排名只能变动一位,这是充要的。

考虑去形式化这个条件,将a排序后,我们有:

  • ani+1bian+i1
  • 不存在j<i满足bi<bj<bi+1bi+1<bj<bi

这样我们其实并不需要考虑a填的情况,如果b一次向外跨过了很多个a,那么我们可以视这些a此时还没有加入,我们只需要限制往内跨的情况出现就好了。

不过这第二个条件依旧不好处理,我们考虑倒着做,那当我们确定一个bibi+1之后,相当于(bi,bi+1)之间的数字就都不能选择了。

考虑dp,设fi,l,r表示目前填了i个,对于现在的bi来说,左边还剩下l个位置,右边还剩下r个位置。

然后每次加入两边的ai,如果al=al+1,那么我们将其视为同一个,右边同理。

时间复杂度:O(n4)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=110,P=1e9+7; ll n,m,a[N],f[N][N][N]; signed main() { scanf("%lld",&n);m=2*n-1; for(ll i=1;i<=m;i++) scanf("%lld",&a[i]); sort(a+1,a+m+1); f[n][0][0]=1; for(ll i=n-1;i>=1;i--){ ll l=i,r=2*n-i; ll dl=(a[l]!=a[l+1]),dr=(a[r]!=a[r-1]); for(ll l=0;l<=m;l++) for(ll r=0;r<=m;r++){ if(!f[i+1][l][r])continue; (f[i][l+dl][r+dr]+=f[i+1][l][r])%=P; for(ll k=0;k<l+dl;k++)(f[i][k][r+dr+1]+=f[i+1][l][r])%=P; for(ll k=0;k<r+dr;k++)(f[i][l+dl+1][k]+=f[i+1][l][r])%=P; } } ll ans=0; for(ll i=0;i<=m;i++) for(ll j=0;j<=m;j++) (ans+=f[1][i][j])%=P; printf("%lld\n",ans); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/16552187.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(49)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示