• soj114 中位数


    题意:给你一个长度为2n-1的数组A,设Bi是A的1~2i-1的中位数。问打乱A,有多少种不同的B序列?

    标程:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int mod=998244353;
     4 const int N=150;
     5 typedef long long ll;
     6 int ans,n,a[N],tmp,dp[N][N][N];
     7 void up(int &x,int y) {x=((ll)x+y)%mod;}
     8 int main()
     9 {
    10   scanf("%d",&n);
    11   for (int i=1;i<=2*n-1;i++) scanf("%d",&a[i]);
    12   sort(a+1,a+2*n);
    13   dp[n][a[n]!=a[n-1]][a[n]!=a[n+1]]=1;
    14   for (int i=n;i>1;i--)
    15   {
    16     int x=(a[i-1]!=a[i-2]),y=(a[2*n-i+1]!=a[2*n-i+2]);
    17     for (int l=0;l<=(n-i+1)*2;l++)
    18       for (int r=0;r<=(n-i+1)*2;r++)
    19       if (tmp=dp[i][l][r])
    20       {
    21          up(dp[i-1][l+x][r+y],tmp);
    22          for (int _l=0;_l<l;_l++) up(dp[i-1][_l+x][r+y+1],tmp);
    23          for (int _r=0;_r<r;_r++) up(dp[i-1][l+x+1][_r+y],tmp);
    24       }
    25   }
    26   for (int i=0;i<=2*n-1;i++)
    27     for (int j=0;j<=2*n-1;j++) up(ans,dp[1][i][j]);
    28   printf("%d
    ",ans);
    29   return 0;
    30 }

    题解:技巧dp

    出题人非常良心,当ai<=2时,答案是2^min(1的个数,2的个数)。

    最后一个中位数是可以直接确定的,由于中位数在序列中最多左右按照数值移动相邻一位因此可以用倒三角表示出每一位中位数的可能集合。

    1 2 3 4 5 6 7

       2 3 4 5 6

          3 4 5 

             4

    直接在该三角形上dp,dp[i][j][k]表示第i层,j表示在该层的候选中位数中,该次选取的中位数的左边有几种数(去重)可取,k表示右边。tmp=dp[i][j][k]。

    左边取掉一列,右边取掉一列,中位数不变:dp[i][j+扩展][k+扩展]+=tmp。

    左边取掉两列,走到上一层中位数应该右移:枚举取到的是哪个中位数,如果能够跳过去,说明中间的几列在之前都没有出现,之前的中位数集合都是不能取它们的,dp[i][j+扩展+1(1表示中间一列变为可取)][r(枚举是哪个中位数,r为该中位数右边还有几个数)+扩展]+=tmp。

    右边取两列同理。

  • 相关阅读:
    PowerDesigner设置线风格(直线,折线。。。)
    使用PowerDesigner画ER图详细教程
    UML学习小结
    UML用例图说明
    UML类图基本画法
    Enterprise Architect与startUML表示UML常用图
    手把手教你使用startuml画用例图
    各种图(流程图,思维导图,UML,拓扑图,ER图)简介
    StartUML 各种类图的例子
    StarUML---推荐一款UML工具(很好很强大)
  • 原文地址:https://www.cnblogs.com/Scx117/p/9064509.html
Copyright © 2020-2023  润新知