有n个城市,每个城市有一个 wi ,如果两座城市满足 wi+wj≥d ,则在两座城市连边。
现在把城市分成2个点集,是2点集之间的边的数量尽量多,求最大数量,方案数。
1≤n≤2000,0≤d≤109
区间dp,将w排序
考虑2个极端情况
1.当w1与wn不连边
此时w1不与任何点连边
2.w1与wn连边
此时wn与所有点连边
然后都懂得
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <functional>
#include <cstdlib>
#include <queue>
#include <stack>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
const int MAXN =(2000+10);
ll w[MAXN],d;
int n,f[MAXN][MAXN],g[MAXN][MAXN]={0};
int vis[MAXN][MAXN]={0};
int T=0;
int work(int i,int j,int x,int l) {
if (vis[l][x]==T) return f[l][x];
vis[l][x]=1; f[l][x]=g[l][x]=0;
if (x>l || x<0) {
return -2000*2000;
}
if (l==1 ) {
g[l][x]=1;
return 0;
}
if (w[i]+w[j]<d) {
if (x==0) {
f[l][x] = work(i+1,j,x,l-1);
g[l][x] = g[l-1][x];
return f[l][x];
}
f[l][x]=work(i+1,j,x-1,l-1);
g[l][x]=g[l-1][x-1];
if (l>x) {
f[l][x] = max( work(i+1,j,x,l-1), f[l][x]);
if (work(i+1,j,x-1,l-1) < work(i+1,j,x,l-1)) g[l][x]=g[l-1][x];
if (work(i+1,j,x-1,l-1) == work(i+1,j,x,l-1)) g[l][x]=(g[l-1][x]+g[l-1][x-1])%F;
}
}
else {
if (x==0) {
f[l][x] = work(i,j-1,x,l-1)+x;
g[l][x] = g[l-1][x];
return f[l][x];
}
f[l][x]=work(i,j-1,x-1,l-1) + l-x;
g[l][x]=g[l-1][x-1];
if (l>x) {
f[l][x]=max(f[l][x],work(i,j-1,x,l-1)+x );
if (work(i,j-1,x-1,l-1) + l-x < work(i,j-1,x,l-1)+x ) g[l][x]=g[l-1][x];
if (work(i,j-1,x-1,l-1) + l-x == work(i,j-1,x,l-1)+x ) g[l][x]=(g[l-1][x]+g[l-1][x-1])%F;
}
}
return f[l][x];
}
int main() {
cin>>n>>d;
For(i,n) cin>>w[i];
sort(w+1,w+1+n);
int ans1=-1,ans2=0;
++T;
// cout<<work(2,4,1,3)<<' '<<g[3][1]<<endl;
Rep(x,n+1) {
work(1,n,x,n);
if (ans1<f[n][x] ) ans1=f[n][x] , ans2 = g[n][x];
else if (ans1 == f[n][x] ) ans2= (ans2+ g[n][x] )%F;
}
cout << ans1 << ' '<< ans2 << endl;
return 0;
}