阿爽爱上了阿秦

题源

 

 即使我们还没有明白香香鸡是什么,起码我们知道它很有趣


上来先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 }

猜你喜欢

转载自www.cnblogs.com/monyhzc/p/12198830.html