题解:考虑没有办法直接dp的原因是每次决策把某个点放入A或者B中不能确定产生了多少贡献。
因此考虑若能将
{
w
n
}
\{w_n\}
{wn}适当排列,使得
∀
i
∈
[
1
,
n
]
⇒
(
∀
j
∈
[
1
,
i
)
→
w
j
+
w
i
≥
m
)
⋃
(
∀
j
∈
[
1
,
i
)
→
w
j
+
w
i
<
m
)
\forall i\in[1,n]\Rightarrow\left(\forall j\in[1,i)\rightarrow w_j+w_i\ge m\right)\bigcup\left(\forall j\in[1,i)\rightarrow w_j+w_i< m\right)
∀i∈[1,n]⇒(∀j∈[1,i)→wj+wi≥m)⋃(∀j∈[1,i)→wj+wi<m),那么每次某个点
x
x
x加入A或者B,根据
w
1
+
w
x
w_1+w_x
w1+wx和
m
m
m的大小关系,可知产生的贡献为0或者另一部分点集的大小。
那么考虑构造这个排列。考虑若
w
1
+
w
n
≥
m
w_1+w_n\ge m
w1+wn≥m,那么可以直接把
w
n
w_n
wn放到
w
1
…
w
n
−
1
w_1\dots w_{n-1}
w1…wn−1的右边。否则可以直接将
w
1
w_1
w1放到
w
2
…
w
n
w_2\dots w_n
w2…wn的右边。递归处理即可。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 1000000007
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const int N=2010;int w[N],a[N],mx[N][N],f[N][N];
int main()
{
int n=inn(),m=inn(),L=1,R=n;
rep(i,1,n) w[i]=inn();sort(w+1,w+n+1);
rep(i,1,n) (w[L]+w[R]>=m?a[i]=w[R--]:a[i]=w[L++]);
reverse(a+1,a+n+1),mx[0][0]=0,f[0][0]=1;
rep(i,1,n) rep(j,0,i)
{
int A,B,&t=f[i][j];
if(a[1]+a[i]<m) A=(j>0?mx[i-1][j-1]:-1),B=(j<i?mx[i-1][j]:-1);
else A=(j>0?mx[i-1][j-1]+i-j:-1),B=(j<i?mx[i-1][j]+j:-1);
mx[i][j]=max(A,B);
if(A>B) t=f[i-1][j-1];else if(A<B) t=f[i-1][j];
else t=f[i-1][j-1]+f[i-1][j],(t>=mod?t-=mod:0);
}
int ans=-1,cnt=0;rep(i,0,n) ans=max(ans,mx[n][i]);
rep(i,0,n) if(mx[n][i]==ans) cnt+=f[n][i],(cnt>=mod?cnt-=mod:0);
return !printf("%d %d\n",ans,cnt);
}