即使我们还没有明白香香鸡是什么,起码我们知道它很有趣
上来先sort
我在场上先考虑朴素dp
记录 dp [ i ][ j ][ k ]为 最后选的是i,选了j个,最小差是 k 的方案数
我们发现要枚举 i , j , k 和从哪转移来的 c
时间O(n^4) 20pts到手
空间不太够,把 j 滚掉就好了
然后wzx说可以不记录 k ?
好像的确可以,O(n^3)
虽然还是 20pts
他没滚掉一维还用了vector爆Memory蛤蛤蛤
然后不管是 n^4, n^3 ,就连我场上水分的爆搜都是20pts
我们考虑已经选出了一个串 S,但具体是什么我们不知道
它的极差是 S [ len ] - S [ 1 ]
然后无论它长什么样,它的最小差 m 不会超过 ( S [ len ] - S [ 1 ] ) / ( len - 1 ) 。所以 m 的上界确定了
于是我们记录 dp [ i ] [ j ] 为前 i 个, 选了 j 个的答案
枚举差有个 1/len , 有 len 个可能转移来的地方, 我们没了一个 n
转移来的地方 c 与转移到的地方 i 的差不能超过 k,所以 c 的上界就是最后一个与 i 差不小于 m 的位置。
我们排序了,所以差不降,因为m不变,所以 c 也不降
一层循环内 c 就会从 1 跑到 j
在最外层枚举个 m ,中间一个现在位置 i , 里面一个很小范围的上一次位置 c
O( n^2 ) 100pts
1 #include<stdio.h> 2 #include<algorithm> 3 #define int long long 4 #define For(i,a,b) for(register int i=(a);i<=(b);i++) 5 using namespace std; 6 const int maxn=1010,mod=998244353; 7 int n,k,mx,h[maxn],c,dp[maxn][maxn],m,ans; 8 inline void init(){ 9 sort(h+1,h+1+n); 10 mx=h[n]/(k-1); 11 For(i,0,n) dp[i][0]=1; 12 } 13 inline int min(int i,int j){return i<j?i:j;} 14 signed main(){ 15 scanf("%lld%lld",&n,&k); 16 For(i,1,n){ 17 scanf("%lld",&h[i]); 18 } 19 init(); 20 For(i,1,mx){ 21 c=0; 22 For(j,1,n){ 23 while(h[j]-h[c+1]>=i) c++; 24 For(t,1,min(j,k)){ 25 dp[j][t]=(dp[j-1][t]+dp[c][t-1])%mod; 26 } 27 } 28 ans=(ans+dp[n][k])%mod; 29 } 30 printf("%lld\n",ans); 31 }