//题意:30001个岛屿自西向东依次编号为0-30000,输入n个编号,表示该岛屿上有宝藏。
//从编号为0处出发向东跳,第一次跳的距离为d。设上一次跳的距离为L(L>0),则当前跳的距离为L-1(L>1)或L或L+1
//输出最多能拿的宝藏数目
//以p[i]表示第i个岛屿的宝藏数目,dp[i][j]表示跳了距离j到第i个岛屿所获得的最多宝藏数,则状态转移方程为:
// dp[i+j-1][j-1]=max(dp[i+j-1][j-1],dp[i][j]+p[i+j-1]) 比上一次跳的距离减少1
// dp[i+j][j]=max(dp[i+j][j],dp[i][j]+p[i+j]) 和上一次跳的距离相等
// dp[i+j+1][j+1]=max(dp[i+j+1][j+1],dp[i][j]+p[i+j+1]) 比上一次跳的距离增加1
//注意这里dp[i][j]中,i,j的取值均为1-30000,如果开30000*30000的数组会超出内存限制。
//第一次跳的距离d,设第k次跳的距离为D[k],以下说明|D[k]-d|<250
//要使|D[k]-d|尽可能大,不妨令D[k]=D[k-1]+1,即每次相比上一次跳动距离增加1
//要使|D[k]-d|尽可能大跳的次数也应该越多,第一次跳的距离d也就应该越小,故取d=1。
//则有D[1]+D[2]+D[3]+……+D[k]=d+(d+1)+(d+2)+……+(d+k-1)<30000
//k*d+k*(k-1)/2<30000
//即k+k*(k-1)/2<30000,k*k+k-60000<0,k<250,就是说在保证|D[k]-d|尽可能大的情况下,跳的次数不会超过250次。
//所以第k次跳的距离与第一次跳的距离之差的绝对值不会超过250
//因此,可以以第一次跳的距离d为基准来表示跳动的距离D。设j=D-d+250,则0<j<500
//实际跳动的距离为D=j+d-250
//这样把规模降到了30000*500
#include<bits/stdc++.h>
using namespace std;
int p[30001];
int dp[30001][501];
int main()
{
int n,d,maxn=0;
int ans;
cin>>n>>d;
int i,j;
memset(dp,-1,sizeof(dp));
memset(p,0,sizeof(p));
for(i=1;i<=n;++i)
{
int temp;
cin>>temp;
++p[temp];
maxn=max(maxn,temp);
}
dp[d][250]=ans=p[d];
for(i=d;i<=maxn;++i)
for(j=1;j<500;++j)
{
if(dp[i][j]==-1) continue;
int D=i+j+d-250; //保持上一次跳动距离跳到的岛屿编号
if(D-1>30000)continue;
if(D-i>1)
{
dp[D-1][j-1]=max(dp[D-1][j-1],dp[i][j]+p[D-1]);
ans=max(dp[D-1][j-1],ans);
}
if(D>30000) continue;
dp[D][j]=max(dp[D][j],dp[i][j]+p[D]);
ans=max(ans,dp[D][j]);
dp[D+1][j+1]=max(dp[D+1][j+1],dp[i][j]+p[D+1]);
ans=max(ans,dp[D+1][j+1]);
}
cout<<ans<<endl;
return 0;
}
//从编号为0处出发向东跳,第一次跳的距离为d。设上一次跳的距离为L(L>0),则当前跳的距离为L-1(L>1)或L或L+1
//输出最多能拿的宝藏数目
//以p[i]表示第i个岛屿的宝藏数目,dp[i][j]表示跳了距离j到第i个岛屿所获得的最多宝藏数,则状态转移方程为:
// dp[i+j-1][j-1]=max(dp[i+j-1][j-1],dp[i][j]+p[i+j-1]) 比上一次跳的距离减少1
// dp[i+j][j]=max(dp[i+j][j],dp[i][j]+p[i+j]) 和上一次跳的距离相等
// dp[i+j+1][j+1]=max(dp[i+j+1][j+1],dp[i][j]+p[i+j+1]) 比上一次跳的距离增加1
//注意这里dp[i][j]中,i,j的取值均为1-30000,如果开30000*30000的数组会超出内存限制。
//第一次跳的距离d,设第k次跳的距离为D[k],以下说明|D[k]-d|<250
//要使|D[k]-d|尽可能大,不妨令D[k]=D[k-1]+1,即每次相比上一次跳动距离增加1
//要使|D[k]-d|尽可能大跳的次数也应该越多,第一次跳的距离d也就应该越小,故取d=1。
//则有D[1]+D[2]+D[3]+……+D[k]=d+(d+1)+(d+2)+……+(d+k-1)<30000
//k*d+k*(k-1)/2<30000
//即k+k*(k-1)/2<30000,k*k+k-60000<0,k<250,就是说在保证|D[k]-d|尽可能大的情况下,跳的次数不会超过250次。
//所以第k次跳的距离与第一次跳的距离之差的绝对值不会超过250
//因此,可以以第一次跳的距离d为基准来表示跳动的距离D。设j=D-d+250,则0<j<500
//实际跳动的距离为D=j+d-250
//这样把规模降到了30000*500
#include<bits/stdc++.h>
using namespace std;
int p[30001];
int dp[30001][501];
int main()
{
int n,d,maxn=0;
int ans;
cin>>n>>d;
int i,j;
memset(dp,-1,sizeof(dp));
memset(p,0,sizeof(p));
for(i=1;i<=n;++i)
{
int temp;
cin>>temp;
++p[temp];
maxn=max(maxn,temp);
}
dp[d][250]=ans=p[d];
for(i=d;i<=maxn;++i)
for(j=1;j<500;++j)
{
if(dp[i][j]==-1) continue;
int D=i+j+d-250; //保持上一次跳动距离跳到的岛屿编号
if(D-1>30000)continue;
if(D-i>1)
{
dp[D-1][j-1]=max(dp[D-1][j-1],dp[i][j]+p[D-1]);
ans=max(dp[D-1][j-1],ans);
}
if(D>30000) continue;
dp[D][j]=max(dp[D][j],dp[i][j]+p[D]);
ans=max(ans,dp[D][j]);
dp[D+1][j+1]=max(dp[D+1][j+1],dp[i][j]+p[D+1]);
ans=max(ans,dp[D+1][j+1]);
}
cout<<ans<<endl;
return 0;
}