• [loj3503]滚榜


    一个小问题:题意中关于$b_{i}$的顺序只需要单调不降即可,相同时可任意选择

    考虑$i$优于$j$的条件,即$val_{i}ge val_{j}+[i>j]$,并记$del_{i,j}=max(a_{i}+[i<j]-a_{j},0)$

    先考虑暴力$o(n!)$枚举最终的排名排名$p_{i}$(其中$p_{1}$为第一名),并判定其是否合法

    根据题目的描述,即要求存在$b_{i}$,满足:

    1.$sum_{i=1}^{n}b_{i}=m$且$b_{p_{n}}le b_{p_{n-1}}le ...le b_{p_{1}}$

    2.$forall 1le i<n,a_{p_{i}}+b_{p_{i}}ge a_{p_{i+1}}+b_{p_{i+1}}+[p_{i}>p_{i+1}]$

    3.$forall 1le i<jle n,a_{p_{j}}+b_{p_{j}}ge a_{p_{i}}+[p_{j}>p_{i}]$

    注意到除去$sum_{i=1}^{n}b_{i}=m$以外,其余条件都限制的是$b_{i}$之差,同时增加$b_{p_{1}}$并不影响后者,换言之每一个$b_{i}$一定取其所有限制条件中的最小值,最终通过调整(增大)$b_{p_{1}}$使其恰等于$m$即可

    更具体的来说,对于$1le i<n$时,满足$b_{p_{i}}=max(max_{1le j<i}del_{p_{j},p_{i}},b_{p_{i+1}}+del_{p_{i+1},p_{i}})$

    (特别的,$b_{p_{n}}=max_{i=1}^{n}del_{i,p_{n}}$)

    求出$b_{i}$后,将其累加并判定是否小于等于$m$即可

    关于这个的计算,可以从后往前,前者的$p_{j}$即所有未出现的元素,同时由于$[p_{i}>p_{j}]$的影响至多为1,必然是在$a_{p_{j}}$最大的基础上选择$p_{j}$最小的,可以$o(2^{n})$预处理出

    综上,即得到一个$o(n!)$的做法,显然无法通过

    事实上,对于$1le i<n$,还满足$max_{1le j<i}del_{p_{j},p_{i}}le b_{p_{i+1}}+del_{p_{i+1},p_{i}}$,换言之,即$max$一定选择后者

    证明比较简单,假设前面最大值在$p_{j}=k$处取到,那么有$b_{p_{i+1}}ge del_{k,p_{i+1}}$,且前者恰为$del_{k,p_{i}}$

    代入后,若前者结果为0,则必然小于等于后者,后者去除max后单调不递增,因此都可以去除,取出后对其抵消即得到$[p_{i}>p_{k}]le [p_{i+1}>k]+[p_{i}>p_{i+1}]$

    对其进行分类讨论,不难得到该式恒成立,即得证

    最终,即有$b_{p_{i}}=b_{p_{i+1}}+del_{p_{i+1},p_{i}}$(这里可能还需要从后往前归纳一下,且$b_{p_{n}}$不变),那么即有$sum_{i=1}^{n}b_{i}=sum_{i=1}^{n-1}icdot del_{p_{i+1},p_{i}}+nmax_{1le ile n}del_{i,p_{n}}$

    现在,即可状压dp,即$f_{S,i,j}$表示满足以下条件的排列数:${p_{1},p_{2},...,p_{|S|}}=S$,$p_{|S|}=i$且$1le ile |S|$在上式中和为$j$

    转移枚举下一个元素,即$f_{Scup{x},x,j+|S|del_{x,i}}=sum_{x otin S}f_{S,i,j}$,最后再计算$nmax_{1le ile n}del_{i,p_{n}}$对答案的影响即可(即要求$jle m-nmax_{1le ile n}del_{i,p_{n}}$)

    最终计算复杂度为$o(n^{2}m2^{n})$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 13
     4 #define M 505
     5 #define ll long long
     6 int n,m,a[N],b[N],tot[1<<N];
     7 ll ans,f[1<<N][N][M];
     8 int del(int x,int y){
     9     return max(a[x]+(y>x)-a[y],0);
    10 }
    11 int main(){
    12     scanf("%d%d",&n,&m);
    13     for(int i=0;i<n;i++)scanf("%d",&a[i]);
    14     for(int i=0;i<(1<<n);i++)tot[i]=tot[i>>1]+(i&1);
    15     for(int i=0;i<n;i++)f[1<<i][i][0]=1;
    16     for(int i=1;i<(1<<n);i++)
    17         for(int j=0;j<n;j++)
    18             if (i&(1<<j)){
    19                 for(int x=0;x<n;x++)
    20                     if (!(i&(1<<x))){
    21                         int s=tot[i]*del(x,j);
    22                         for(int k=s;k<=m;k++)f[i^(1<<x)][x][k]+=f[i][j][k-s];
    23                     }
    24             }
    25     int mx=0;
    26     for(int i=1;i<n;i++)
    27         if (a[i]>a[mx])mx=i;
    28     for(int i=0;i<n;i++)
    29         for(int j=0;j<=m-n*del(mx,i);j++)ans+=f[(1<<n)-1][i][j];
    30     printf("%lld",ans);
    31 }
    View Code
  • 相关阅读:
    转载 centos7安装kafka_2.11-1.0.0 新手入门(集群)
    Kafka得介绍与单节点部署
    MVC Areas
    Session如何保存在sql数据库中
    AsposeCell特定格式表格
    DataTable数据修改,换列
    A1095 Cars on Campus (30 分)
    A1075 PAT Judge (25 分)
    A1016 Phone Bills (25 分)
    A1082 Read Number in Chinese (25 分)
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14666963.html
Copyright © 2020-2023  润新知