当前位置: 代码迷 >> 综合 >> 【DP】hihocoder1596 Beautiful Sequence
  详细解决方案

【DP】hihocoder1596 Beautiful Sequence

热度:47   发布时间:2023-09-27 08:32:10.0

描述

Consider a positive integer sequence a[1], …, a[n] (n ≥ 3). If for every 2 ≤ i ≤ n-1, a[i-1] + a[i+1] ≥ 2 × a[i] holds, then we say this sequence is beautiful.

Now you have a positive integer sequence b[1], …, b[n]. Please calculate the probability P that the resulting sequence is beautiful after uniformly random shuffling sequence b.

You’re only required to output (P × (n!)) mod 1000000007. (Obviously P × (n!) is an integer)


分析

答案其实求的就是合法的方案总数,
考虑它的限定条件:a[i?1]+a[i+1]2?a[i]
用图像来表示这个数列:
【DP】hihocoder1596 Beautiful Sequence
很容易发现,一旦存在一个波峰:
那么a[i]>a[i?1],a[i]>a[i+1],a[i]?2>a[i?1]+a[i+1],一定矛盾
因此,不可能存在波峰情况。

因此,这个数列的图像的大致趋势就可以确定了:
【DP】hihocoder1596 Beautiful Sequence
(图中的波谷可能在边界,此时就是一个递增/递减的序列了)

基于这种情况,我们就可以通过DP来解决问题了:
首先将b数组排序,再将其分成两组,
我们设dp[i][j][k][l]表示:
最大值所在的序列最大的数为bi
最大值不在的序列最大的数为bj
最大值所在的序列次大的数为bk
最大值不在的序列次大的数为bl

转移方程就很好想了:
枚举每一个状态,向其中加入bi+1

dp[i+1][j][i][l]+=dp[i][j][k][l]

dp[i+1][i][j][k]+=dp[i][j][k][l]

注意:最小值不参与这些计算。

答案就是

0jn,0k<n0<l<jdp[n][j][k][l]

不用特别判断 j=k 等非法的情况,因为那些情况中dp值一定为0

因为最小值的取值是任意的,所以设有K个最小值,
那么答案就得再乘上 K

初始状态dp[1][1][0][0]=1,这个状态有点非法,但综合一下我考场上的几种写法,这样做相对来说后面好写一点。
因此,在转移的时候就要特别考虑到从边界转移的问题,所以要加几个恶心的max,来保证初始状态能够转移出去。
【DP】hihocoder1596 Beautiful Sequence


当时那场hihocoder我就是做了这道垃圾水题,就进了前20,拿了一个滴滴出行的玩偶。
第一次网赛拿奖品,还是挺开心的。这道题我当时调了很久,考试结束前18分钟才做出来(蒟蒻属性暴露无遗),最后半个小时的时候,真心觉得调不出来了,但想了想还是拼了一下,居然过了。不到最后一刻真不能认怂啊。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define SF scanf
#define PF printf
using namespace std;
void Read(int &x){char c;bool flag=0;while(c=getchar(),c!=EOF&&(c<'0'||c>'9')&&c!='-');if(c=='-'){ c=getchar();flag=1;}x=c-'0';while(c=getchar(),c!=EOF&&c>='0'&&c<='9')x=x*10+c-'0';if(flag)x=-x;
} #define MAXN 65
#define MOD 1000000007
long long dp[MAXN][MAXN][MAXN][MAXN];
int n,k,tot;
long long a[MAXN],b[MAXN];
long long jc(long long x){long long res=1;while(x){res*=x;res%=MOD;x--;}return res%MOD;
}
int main(){Read(n);for(int i=1;i<=n;i++)SF("%lld",&b[i]);sort(b+1,b+1+n);int st=1;for(;b[st]==b[1]&&st<=n;st++);a[1]=b[1];for(int i=2;i<=n-st+2;i++)a[i]=b[st+i-2];if(st>n){PF("%lld",jc(st-1));return 0;}n=n-st+2;dp[1][1][0][0]=1;for(int i=1;i<n;i++)for(int j=1;j<max(2,i);j++)for(int k=0;k<max(1,i);k++)for(int l=0;l<max(1,j);l++){if((a[i+1]>=2*a[i]-a[k])||k==0){dp[i+1][j][i][l]+=dp[i][j][k][l];dp[i+1][j][i][l]%=MOD;  }if((a[i+1]>=2*a[j]-a[l])||l==0){dp[i+1][i][j][k]+=dp[i][j][k][l];dp[i+1][i][j][k]%=MOD;}}/*for(int i=0;i<=n;i++)for(int j=0;j<=i;j++)for(int k=0;k<=i;k++)for(int l=0;l<=j;l++)PF("(%lld %d %d %d %d)\n",dp[i][j][k][l],i,j,k,l);*/long long ans=0;for(int i=0;i<n;i++)for(int k=0;k<n;k++)for(int l=0;l<max(1,i);l++){ans+=dp[n][i][k][l];ans%=MOD;   }PF("%lld",(ans*jc(st-1))%MOD);
}
  相关解决方案