#include <bits/stdc++.h>
using namespace std ;
const int inf=0x3f3f3f3f ;
const int D=400 ;
const int N=3e4 ;
int cnt[N+10];
int dp[N+10][2*D+10] ;
int n,d,x,ans ;
int main(){
    scanf("%d%d",&n,&d) ;
    for (int i=1;i<=n;i++){
        scanf("%d",&x);
        cnt[x]++ ;
    }
    for (int i=0;i<=N;i++){
        for (int j=-D;j<=D;j++)
        dp[i][j+D]=-inf ;
    }
    dp[d][D]=cnt[0]+cnt[d] ;
    for (int i=d;i<=N;i++){
        for (int j=-D;j<=D;j++){
            if (dp[i][j+D]==-inf){
                continue ;
            }
            for (int z=-1;z<=1;z++){
                int len=j+d+z ;
                if (j+z < -D || j+z >D || len<1 || i+len>N) continue ;
                dp[i+len][j+z+D]=max(dp[i+len][j+z+D],dp[i][j+D]+cnt[i+len]) ;
            }
        }
    }
    ans=0 ;
    for (int i=0;i<=N;i++){
        for (int j=-D;j<=D;j++){
            ans=max(ans,dp[i][j+D]) ;
        }
    }
    printf("%d\n",ans) ;
    return 0 ;
}


#include<bits/stdc++.h>
using namespace std;

struct Solution {
	int n,D;
	vector<int> a;
	vector<vector<int> > f;

	int dfs(int s, int d) {
		if(s > 30000) return 0;
		if(f[d].size() == 0) {
			f[d].resize(30001);
			for(int i = 0; i <= 30000; ++i) {
				f[d][i] = -1;
			}
		}
		int ans = 0;
		if(f[d][s] != -1) return f[d][s];
		for(int t = -1; t <= 1; t++){
			if(d + t <= 0) continue;
			ans = max(ans, dfs(s + d, d + t));
		}
		return f[d][s] = ans + a[s];
	}

	void Solve() {
		scanf("%d%d", &n, &D);
		f.resize(30001);
		a.resize(30001);
		for(int i = 1; i <= n; ++i){
			int x;
			scanf("%d", &x);
			++a[x];
		}
		printf("%d\n", dfs(0, D));
	}
};

int main(){
	Solution().Solve();
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

unordered_map<int, int> dp[30002];

int gems[30002];

int n, d;

int maxIsland = -1;

int solve(int islandOn, int previousJumpLength) {
  // cout << "hello" << endl;
  if(islandOn > maxIsland) {
    return 0;
  }
  // cout << islandOn << " " << previousJumpLength << endl;
  if(dp[islandOn].find(previousJumpLength) != dp[islandOn].end()) {
    return dp[islandOn][previousJumpLength];
  }
  int ans = gems[islandOn];
  int adder = 0;
  for(int i = -1; i <= 1; i++ ) {
    if(previousJumpLength + i + islandOn >= 30001) continue;
    if(previousJumpLength + i <= 0) continue;
    int newIsland = previousJumpLength + i + islandOn;
    if(newIsland > maxIsland) continue;
    adder = max(adder, solve(newIsland, previousJumpLength + i));
  }
  ans += adder;
  dp[islandOn][previousJumpLength] = ans;
  return ans;
}

int main() {
  cin >> n >> d;
  for(int i = 0; i < n; i++ ) {
    int x;
    cin >> x;
    maxIsland = max(maxIsland, x);
    gems[x]++;
  }
  cout << solve(d, d) << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

int dp[30002][492];

int gems[30002];

int n, d;

int maxIsland = -1;

int of(int x) {
  return 246 + d - x;
}

int solve(int islandOn, int previousJumpLength) {
  // cout << "hello" << endl;
  if(islandOn > maxIsland) {
    return 0;
  }
  // cout << islandOn << " " << previousJumpLength << endl;
  if(dp[islandOn][of(previousJumpLength)] != -1) {
    return dp[islandOn][of(previousJumpLength)];
  }
  int ans = gems[islandOn];
  int adder = 0;
  for(int i = -1; i <= 1; i++ ) {
    if(previousJumpLength + i + islandOn >= 30001) continue;
    if(previousJumpLength + i <= 0) continue;
    int newIsland = previousJumpLength + i + islandOn;
    if(newIsland > maxIsland) continue;
    adder = max(adder, solve(newIsland, previousJumpLength + i));
  }
  ans += adder;
  dp[islandOn][of(previousJumpLength)] = ans;
  return ans;
}

int main() {
  for(int i = 0; i < 30002; i++ ) {
    for(int j = 0; j < 492; j++ ) {
      dp[i][j] = -1;
    }
  }
  cin >> n >> d;
  for(int i = 0; i < n; i++ ) {
    int x;
    cin >> x;
    maxIsland = max(maxIsland, x);
    gems[x]++;
  }
  cout << solve(d, d) << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

int dp[30002][492];

int gems[30002];

int n, d;

int maxIsland = -1;

int solve(int islandOn, int previousJumpLength) {
  // cout << "hello" << endl;
  if(islandOn > maxIsland) {
    return 0;
  }
  // cout << islandOn << " " << previousJumpLength << endl;
  if(dp[islandOn][d - previousJumpLength] != -1) {
    return dp[islandOn][previousJumpLength];
  }
  int ans = gems[islandOn];
  int adder = 0;
  for(int i = -1; i <= 1; i++ ) {
    if(previousJumpLength + i + islandOn >= 30001) continue;
    if(previousJumpLength + i <= 0) continue;
    int newIsland = previousJumpLength + i + islandOn;
    if(newIsland > maxIsland) continue;
    adder = max(adder, solve(newIsland, previousJumpLength + i));
  }
  ans += adder;
  dp[islandOn][d - previousJumpLength] = ans;
  return ans;
}

int main() {
  for(int i = 0; i < 30002; i++ ) {
    for(int j = 0; j < 492; j++ ) {
      dp[i][j] = -1;
    }
  }
  cin >> n >> d;
  for(int i = 0; i < n; i++ ) {
    int x;
    cin >> x;
    maxIsland = max(maxIsland, x);
    gems[x]++;
  }
  cout << solve(d, d) << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

int dp[30002][492];

int gems[30002];

int n, d;

int maxIsland = -1;

int solve(int islandOn, int previousJumpLength) {
  // cout << "hello" << endl;
  if(islandOn > maxIsland) {
    return 0;
  }
  // cout << islandOn << " " << previousJumpLength << endl;
  if(dp[islandOn][d - previousJumpLength] != -1) {
    return dp[islandOn][previousJumpLength];
  }
  int ans = gems[islandOn];
  int adder = 0;
  for(int i = -1; i <= 1; i++ ) {
    if(previousJumpLength + i + islandOn >= 30001) continue;
    if(previousJumpLength + i <= 0) continue;
    int newIsland = previousJumpLength + i + islandOn;
    if(newIsland > maxIsland) continue;
    adder = max(adder, solve(newIsland, previousJumpLength + i));
  }
  ans += adder;
  dp[islandOn][246 + d - previousJumpLength] = ans;
  return ans;
}

int main() {
  for(int i = 0; i < 30002; i++ ) {
    for(int j = 0; j < 492; j++ ) {
      dp[i][j] = -1;
    }
  }
  cin >> n >> d;
  for(int i = 0; i < n; i++ ) {
    int x;
    cin >> x;
    maxIsland = max(maxIsland, x);
    gems[x]++;
  }
  cout << solve(d, d) << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

int dp[30002][492];

int gems[30002];

int n, d;

int maxIsland = -1;

int solve(int islandOn, int previousJumpLength) {
  // cout << "hello" << endl;
  if(islandOn > maxIsland) {
    return 0;
  }
  // cout << islandOn << " " << previousJumpLength << endl;
  if(dp[islandOn][d - previousJumpLength]) {
    return dp[islandOn][previousJumpLength];
  }
  int ans = gems[islandOn];
  int adder = 0;
  for(int i = -1; i <= 1; i++ ) {
    if(previousJumpLength + i + islandOn >= 30001) continue;
    if(previousJumpLength + i <= 0) continue;
    int newIsland = previousJumpLength + i + islandOn;
    if(newIsland > maxIsland) continue;
    adder = max(adder, solve(newIsland, previousJumpLength + i));
  }
  ans += adder;
  dp[islandOn][d - previousJumpLength] = ans;
  return ans;
}

int main() {
  cin >> n >> d;
  for(int i = 0; i < n; i++ ) {
    int x;
    cin >> x;
    maxIsland = max(maxIsland, x);
    gems[x]++;
  }
  cout << solve(d, d) << endl;
  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll	long long int
#define ull	unsigned long long int
#define	 mp	make_pair
#define pb	push_back
#define chota(a)	transform(a.begin(),a.end(),a.begin(),::tolower)
#define speed	ios_base::sync_with_stdio(0)
#define	llmax	100000000000000
#define	rep(i,n)	for(int i=0;i<n;i++)
#define rep1(i,n)	for(int i=1;i<=n;i++)
#define	distance(a,b,c,d)	double add(int a,int b,int x,int y){	return sqrt((ll)(x-a)*(x-a)+(ll)(y-b)*(y-b));}
#define pure	cout<<fixed<<setprecision(18)
#define hoga	return 0
#define mod	1000000007
#define	FF	first
#define	SS	second
#define	all(v)	v.begin(),v.end()
#define	scani(v)	scanf("%d",&n)

typedef	pair<int,int> pii;
typedef pair<ll,int>  pli;
typedef pair<ll,ll>   pll;
typedef pair<int,ll>  pil;

void swap(int *a,int *b)
{	int temp=*a;
	*a=*b;
	*b=temp;
}

ll power(ll a,ll b)
{	ll x=1;
	ll y=a;
	while(b>0)
	{	if(b&1)
		{	x=x*y;
			x%=mod;
		}
		y=y*y;
		y%=mod;
		b/=2;
	}
return x;
}

ll inver(ll a)
{	return power(a,mod-2);
}

int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};

int gcd(int a,int b)
{	while(b!=0)
	{	int temp=a;
		a=b;
		b=temp%a;
	}
	return a;
}

int innumber(char c)
{	return c-'0';
}

bool isprime(ll x)
{	for(ll i=2;i<=sqrt(x);i++)
	{	if(x%i==0)return false;
	}
	return true;
}

//bool prime[10000005];

//vector<ll> //prino;
//vector<int>	noof[10000005];
/*
void pre()
{	prime[0]=prime[1]=true;
	for(ll i=2;i<=10000000;i++)
	{	if(!prime[i])
		{	noof[i].pb(i);

			for(ll j=2*i;j<=10000000;j+=i)
			{	prime[j]=true;
				noof[j].pb(i);

			}
		}
	}

}*/
const int N=30002;
int dp[N][800];
int OFF=0;
int cnt[N];

int n,d;
int solve(int index,int len)
{	if(len<0)return 0;
	if(len>N)return 0;
	if(index>N)return 0;

	if(dp[index][len-OFF+256]!=-1)return dp[index][len-OFF+256];
int temp=0;

	if(len>=2)
	{	temp=cnt[index]+solve(index+len,len);
		temp=max(temp,(cnt[index]+solve(index+len-1,len-1)));
		temp=max(temp,(cnt[index]+solve(index+len+1,len+1)));
	}
	else	if(len>1)
		{	temp=cnt[index]+solve(index+len,len);
		//temp=max(temp,cnt[index]+solve(index+len-1,len-1));
			temp=max(temp,(cnt[index]+solve(index+len+1,len+1)));
		}
	dp[index][len-OFF+256]=temp;
	return temp;
}

int main()
{	speed;
	cin>>n>>d;
	OFF=d;
	memset(dp,-1,sizeof dp);
for(int i=0;i<n;i++)
	{	int x;
		cin>>x;
			cnt[x]++;

	}

	cout<<n<<" " <<d<<" " <<solve(d,d)<<endl;

	hoga;

}


#include<bits/stdc++.h>
using namespace std;
#define ll	long long int
#define ull	unsigned long long int
#define	 mp	make_pair
#define pb	push_back
#define chota(a)	transform(a.begin(),a.end(),a.begin(),::tolower)
#define speed	ios_base::sync_with_stdio(0)
#define	llmax	100000000000000
#define	rep(i,n)	for(int i=0;i<n;i++)
#define rep1(i,n)	for(int i=1;i<=n;i++)
#define	distance(a,b,c,d)	double add(int a,int b,int x,int y){	return sqrt((ll)(x-a)*(x-a)+(ll)(y-b)*(y-b));}
#define pure	cout<<fixed<<setprecision(18)
#define hoga	return 0
#define mod	1000000007
#define	FF	first
#define	SS	second
#define	all(v)	v.begin(),v.end()
#define	scani(v)	scanf("%d",&n)

typedef	pair<int,int> pii;
typedef pair<ll,int>  pli;
typedef pair<ll,ll>   pll;
typedef pair<int,ll>  pil;

void swap(int *a,int *b)
{	int temp=*a;
	*a=*b;
	*b=temp;
}

ll power(ll a,ll b)
{	ll x=1;
	ll y=a;
	while(b>0)
	{	if(b&1)
		{	x=x*y;
			x%=mod;
		}
		y=y*y;
		y%=mod;
		b/=2;
	}
return x;
}

ll inver(ll a)
{	return power(a,mod-2);
}

int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};

int gcd(int a,int b)
{	while(b!=0)
	{	int temp=a;
		a=b;
		b=temp%a;
	}
	return a;
}

int innumber(char c)
{	return c-'0';
}

bool isprime(ll x)
{	for(ll i=2;i<=sqrt(x);i++)
	{	if(x%i==0)return false;
	}
	return true;
}

//bool prime[10000005];

//vector<ll> //prino;
//vector<int>	noof[10000005];
/*
void pre()
{	prime[0]=prime[1]=true;
	for(ll i=2;i<=10000000;i++)
	{	if(!prime[i])
		{	noof[i].pb(i);

			for(ll j=2*i;j<=10000000;j+=i)
			{	prime[j]=true;
				noof[j].pb(i);

			}
		}
	}

}*/
const int N=30010;
int dp[N][800];
int OFF=0;
int cnt[N];

int n,d;
int solve(int index,int len)
{	if(len<0)return 0;
	if(len>N)return 0;
	if(index>N)return 0;

	if(dp[index][len-OFF+256]!=-1)return dp[index][len-OFF+256];
int temp=0;

	if(len>=2)
	{	temp=cnt[index]+solve(index+len,len);
		temp=max(temp,cnt[index]+solve(index+len-1,len-1));
		temp=max(temp,cnt[index]+solve(index+len+1,len+1));
	}
	else	if(len>1)
		{	temp=cnt[index]+solve(index+len,len);
		//temp=max(temp,cnt[index]+solve(index+len-1,len-1));
			temp=max(temp,cnt[index]+solve(index+len+1,len+1));
		}
	dp[index][len-OFF+256]=temp;
	return temp;
}

int main()
{	speed;
	cin>>n>>d;
	OFF=d;
	memset(dp,-1,sizeof dp);
for(int i=0;i<n;i++)
	{	int x;
		cin>>x;
			cnt[x]++;

	}

	cout<<solve(d,d)<<endl;

	hoga;

}


#include<bits/stdc++.h>
using namespace std;
#define ll	long long int
#define ull	unsigned long long int
#define	 mp	make_pair
#define pb	push_back
#define chota(a)	transform(a.begin(),a.end(),a.begin(),::tolower)
#define speed	ios_base::sync_with_stdio(0)
#define	llmax	100000000000000
#define	rep(i,n)	for(int i=0;i<n;i++)
#define rep1(i,n)	for(int i=1;i<=n;i++)
#define	distance(a,b,c,d)	double add(int a,int b,int x,int y){	return sqrt((ll)(x-a)*(x-a)+(ll)(y-b)*(y-b));}
#define pure	cout<<fixed<<setprecision(18)
#define hoga	return 0
#define mod	1000000007
#define	FF	first
#define	SS	second
#define	all(v)	v.begin(),v.end()
#define	scani(v)	scanf("%d",&n)

typedef	pair<int,int> pii;
typedef pair<ll,int>  pli;
typedef pair<ll,ll>   pll;
typedef pair<int,ll>  pil;

void swap(int *a,int *b)
{	int temp=*a;
	*a=*b;
	*b=temp;
}

ll power(ll a,ll b)
{	ll x=1;
	ll y=a;
	while(b>0)
	{	if(b&1)
		{	x=x*y;
			x%=mod;
		}
		y=y*y;
		y%=mod;
		b/=2;
	}
return x;
}

ll inver(ll a)
{	return power(a,mod-2);
}

int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};

int gcd(int a,int b)
{	while(b!=0)
	{	int temp=a;
		a=b;
		b=temp%a;
	}
	return a;
}

int innumber(char c)
{	return c-'0';
}

bool isprime(ll x)
{	for(ll i=2;i<=sqrt(x);i++)
	{	if(x%i==0)return false;
	}
	return true;
}

//bool prime[10000005];

//vector<ll> //prino;
//vector<int>	noof[10000005];
/*
void pre()
{	prime[0]=prime[1]=true;
	for(ll i=2;i<=10000000;i++)
	{	if(!prime[i])
		{	noof[i].pb(i);

			for(ll j=2*i;j<=10000000;j+=i)
			{	prime[j]=true;
				noof[j].pb(i);

			}
		}
	}

}*/
const int N=30002;
int dp[N][800];
int OFF=0;
int cnt[N];

int n,d;
int solve(int index,int len)
{	if(len<0)return 0;
	if(len>N)return 0;
	if(index>N)return 0;

	if(dp[index][len-OFF+256]!=-1)return dp[index][len-OFF+256];
int temp=0;

	if(len>=2)
	{	temp=cnt[index]+solve(index+len,len);
		temp=max(temp,(cnt[index]+solve(index+len-1,len-1)));
		temp=max(temp,(cnt[index]+solve(index+len+1,len+1)));
	}
	else	if(len>1)
		{	temp=cnt[index]+solve(index+len,len);
		//temp=max(temp,cnt[index]+solve(index+len-1,len-1));
			temp=max(temp,(cnt[index]+solve(index+len+1,len+1)));
		}
	dp[index][len-OFF+256]=temp;
	return temp;
}

int main()
{	speed;
	cin>>n>>d;
	OFF=d;
	memset(dp,-1,sizeof dp);
for(int i=0;i<n;i++)
	{	int x;
		cin>>x;
			cnt[x]++;

	}

	cout<<solve(d,d)<<endl;

	hoga;

}


#include<bits/stdc++.h>
using namespace std;
#define ll	long long int
#define ull	unsigned long long int
#define	 mp	make_pair
#define pb	push_back
#define chota(a)	transform(a.begin(),a.end(),a.begin(),::tolower)
#define speed	ios_base::sync_with_stdio(0)
#define	llmax	100000000000000
#define	rep(i,n)	for(int i=0;i<n;i++)
#define rep1(i,n)	for(int i=1;i<=n;i++)
#define	distance(a,b,c,d)	double add(int a,int b,int x,int y){	return sqrt((ll)(x-a)*(x-a)+(ll)(y-b)*(y-b));}
#define pure	cout<<fixed<<setprecision(18)
#define hoga	return 0
#define mod	1000000007
#define	FF	first
#define	SS	second
#define	all(v)	v.begin(),v.end()
#define	scani(v)	scanf("%d",&n)

typedef	pair<int,int> pii;
typedef pair<ll,int>  pli;
typedef pair<ll,ll>   pll;
typedef pair<int,ll>  pil;

void swap(int *a,int *b)
{	int temp=*a;
	*a=*b;
	*b=temp;
}

ll power(ll a,ll b)
{	ll x=1;
	ll y=a;
	while(b>0)
	{	if(b&1)
		{	x=x*y;
			x%=mod;
		}
		y=y*y;
		y%=mod;
		b/=2;
	}
return x;
}

ll inver(ll a)
{	return power(a,mod-2);
}

int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};

int gcd(int a,int b)
{	while(b!=0)
	{	int temp=a;
		a=b;
		b=temp%a;
	}
	return a;
}

int innumber(char c)
{	return c-'0';
}

bool isprime(ll x)
{	for(ll i=2;i<=sqrt(x);i++)
	{	if(x%i==0)return false;
	}
	return true;
}

//bool prime[10000005];

//vector<ll> //prino;
//vector<int>	noof[10000005];
/*
void pre()
{	prime[0]=prime[1]=true;
	for(ll i=2;i<=10000000;i++)
	{	if(!prime[i])
		{	noof[i].pb(i);

			for(ll j=2*i;j<=10000000;j+=i)
			{	prime[j]=true;
				noof[j].pb(i);

			}
		}
	}

}*/
const int N=30002;
int dp[N][500];
int OFF=0;
int cnt[N];
bool used[N][500];

int n,d;
int solve(int index,int len)
{	if(len<0)return 0;
	if(index>=N)return 0;
	int j=len-OFF-250;

	if(used[index][j])return dp[index][j];
	used[index][j]=true;
	int temp=0;

	if(len==1)
	{	temp=cnt[index]+max(solve(index+len,len),solve(index+len+1,len+1));
	}
	else
	{	temp=cnt[index]+max(solve(index+len,len),max(solve(index+len-1,len-1),solve(index+len+1,len+1)));
	}
	dp[index][j]=temp;
	return temp;

}

int main()
{	speed;
	cin>>n>>d;
	OFF=d;
	memset(dp,-1,sizeof dp);
for(int i=0;i<n;i++)
	{	int x;
		cin>>x;
			cnt[x]++;

	}

	printf("%d\n",solve(d,d));

	hoga;

}


#include<bits/stdc++.h>
using namespace std;
#define ll	long long int
#define ull	unsigned long long int
#define	 mp	make_pair
#define pb	push_back
#define chota(a)	transform(a.begin(),a.end(),a.begin(),::tolower)
#define speed	ios_base::sync_with_stdio(0)
#define	llmax	100000000000000
#define	rep(i,n)	for(int i=0;i<n;i++)
#define rep1(i,n)	for(int i=1;i<=n;i++)
#define	distance(a,b,c,d)	double add(int a,int b,int x,int y){	return sqrt((ll)(x-a)*(x-a)+(ll)(y-b)*(y-b));}
#define pure	cout<<fixed<<setprecision(18)
#define hoga	return 0
#define mod	1000000007
#define	FF	first
#define	SS	second
#define	all(v)	v.begin(),v.end()
#define	scani(v)	scanf("%d",&n)

typedef	pair<int,int> pii;
typedef pair<ll,int>  pli;
typedef pair<ll,ll>   pll;
typedef pair<int,ll>  pil;

void swap(int *a,int *b)
{	int temp=*a;
	*a=*b;
	*b=temp;
}

ll power(ll a,ll b)
{	ll x=1;
	ll y=a;
	while(b>0)
	{	if(b&1)
		{	x=x*y;
			x%=mod;
		}
		y=y*y;
		y%=mod;
		b/=2;
	}
return x;
}

ll inver(ll a)
{	return power(a,mod-2);
}

int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};

int gcd(int a,int b)
{	while(b!=0)
	{	int temp=a;
		a=b;
		b=temp%a;
	}
	return a;
}

int innumber(char c)
{	return c-'0';
}

bool isprime(ll x)
{	for(ll i=2;i<=sqrt(x);i++)
	{	if(x%i==0)return false;
	}
	return true;
}

//bool prime[10000005];

//vector<ll> //prino;
//vector<int>	noof[10000005];
/*
void pre()
{	prime[0]=prime[1]=true;
	for(ll i=2;i<=10000000;i++)
	{	if(!prime[i])
		{	noof[i].pb(i);

			for(ll j=2*i;j<=10000000;j+=i)
			{	prime[j]=true;
				noof[j].pb(i);

			}
		}
	}

}*/
const int N=30010;
int dp[N][800];
int OFF=0;
int cnt[N];

int n,d;
int solve(int index,int len)
{	if(len<0)return 0;
	if(len>N)return 0;
	if(index>N)return 0;

	if(dp[index][len-OFF+256]!=-1)return dp[index][len-OFF+256];
int temp=0;

	if(len>=2)
	{	temp=cnt[index]+solve(index+len,len);
		temp=max(temp,cnt[index]+solve(index+len-1,len-1));
		temp=max(temp,cnt[index]+solve(index+len+1,len+1));
	}
	else	if(len>1)
		{	temp=cnt[index]+solve(index+len,len);
		//temp=max(temp,cnt[index]+solve(index+len-1,len-1));
			temp=max(temp,cnt[index]+solve(index+len+1,len+1));
		}
	dp[index][len-OFF+256]=temp;
	return temp;
}

int main()
{	speed;
	cin>>n>>d;
	OFF=d;
	memset(dp,-1,sizeof dp);
for(int i=0;i<n;i++)
	{	int x;
		cin>>x;
			cnt[x]++;

	}

	int ans=cnt[0]+solve(d,d);
	cout<<ans<<endl;
	hoga;

}


#include<bits/stdc++.h>
using namespace std;
#define ll	long long int
#define ull	unsigned long long int
#define	 mp	make_pair
#define pb	push_back
#define chota(a)	transform(a.begin(),a.end(),a.begin(),::tolower)
#define speed	ios_base::sync_with_stdio(0)
#define	llmax	100000000000000
#define	rep(i,n)	for(int i=0;i<n;i++)
#define rep1(i,n)	for(int i=1;i<=n;i++)
#define	distance(a,b,c,d)	double add(int a,int b,int x,int y){	return sqrt((ll)(x-a)*(x-a)+(ll)(y-b)*(y-b));}
#define pure	cout<<fixed<<setprecision(18)
#define hoga	return 0
#define mod	1000000007
#define	FF	first
#define	SS	second
#define	all(v)	v.begin(),v.end()
#define	scani(v)	scanf("%d",&n)

typedef	pair<int,int> pii;
typedef pair<ll,int>  pli;
typedef pair<ll,ll>   pll;
typedef pair<int,ll>  pil;

void swap(int *a,int *b)
{	int temp=*a;
	*a=*b;
	*b=temp;
}

ll power(ll a,ll b)
{	ll x=1;
	ll y=a;
	while(b>0)
	{	if(b&1)
		{	x=x*y;
			x%=mod;
		}
		y=y*y;
		y%=mod;
		b/=2;
	}
return x;
}

ll inver(ll a)
{	return power(a,mod-2);
}

int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};

int gcd(int a,int b)
{	while(b!=0)
	{	int temp=a;
		a=b;
		b=temp%a;
	}
	return a;
}

int innumber(char c)
{	return c-'0';
}

bool isprime(ll x)
{	for(ll i=2;i<=sqrt(x);i++)
	{	if(x%i==0)return false;
	}
	return true;
}

//bool prime[10000005];

//vector<ll> //prino;
//vector<int>	noof[10000005];
/*
void pre()
{	prime[0]=prime[1]=true;
	for(ll i=2;i<=10000000;i++)
	{	if(!prime[i])
		{	noof[i].pb(i);

			for(ll j=2*i;j<=10000000;j+=i)
			{	prime[j]=true;
				noof[j].pb(i);

			}
		}
	}

}*/
const int N=30010;
int dp[N][800];
int OFF=0;
int cnt[N];

int n,d;
int solve(int index,int len)
{	if(len<0)return 0;
	if(len>N)return 0;
	if(index>N)return 0;

	if(dp[index][len-OFF+256]!=-1)return dp[index][len-OFF+256];
int temp=0;

	if(len>=2)
	{	temp=cnt[index]+solve(index+len,len);
		temp=max(temp,cnt[index]+solve(index+len-1,len-1));
		temp=max(temp,cnt[index]+solve(index+len+1,len+1));
	}
	else	if(len>1)
		{	temp=cnt[index]+solve(index+len,len);
		//temp=max(temp,cnt[index]+solve(index+len-1,len-1));
			temp=max(temp,cnt[index]+solve(index+len+1,len+1));
		}
	dp[index][len-OFF+256]=temp;
	return temp;
}

int main()
{	speed;
	cin>>n>>d;
	OFF=d;
	memset(dp,-1,sizeof dp);
for(int i=0;i<n;i++)
	{	int x;
		cin>>x;
			cnt[x]++;

	}

	int ans=0;
	ans=cnt[0]+solve(d,d);
	cout<<ans<<endl;
	hoga;

}


#include<bits/stdc++.h>
using namespace std;
#define ll	long long int
#define ull	unsigned long long int
#define	 mp	make_pair
#define pb	push_back
#define chota(a)	transform(a.begin(),a.end(),a.begin(),::tolower)
#define speed	ios_base::sync_with_stdio(0)
#define	llmax	100000000000000
#define	rep(i,n)	for(int i=0;i<n;i++)
#define rep1(i,n)	for(int i=1;i<=n;i++)
#define	distance(a,b,c,d)	double add(int a,int b,int x,int y){	return sqrt((ll)(x-a)*(x-a)+(ll)(y-b)*(y-b));}
#define pure	cout<<fixed<<setprecision(18)
#define hoga	return 0
#define mod	1000000007
#define	FF	first
#define	SS	second
#define	all(v)	v.begin(),v.end()
#define	scani(v)	scanf("%d",&n)

typedef	pair<int,int> pii;
typedef pair<ll,int>  pli;
typedef pair<ll,ll>   pll;
typedef pair<int,ll>  pil;

void swap(int *a,int *b)
{	int temp=*a;
	*a=*b;
	*b=temp;
}

ll power(ll a,ll b)
{	ll x=1;
	ll y=a;
	while(b>0)
	{	if(b&1)
		{	x=x*y;
			x%=mod;
		}
		y=y*y;
		y%=mod;
		b/=2;
	}
return x;
}

ll inver(ll a)
{	return power(a,mod-2);
}

int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};

int gcd(int a,int b)
{	while(b!=0)
	{	int temp=a;
		a=b;
		b=temp%a;
	}
	return a;
}

int innumber(char c)
{	return c-'0';
}

bool isprime(ll x)
{	for(ll i=2;i<=sqrt(x);i++)
	{	if(x%i==0)return false;
	}
	return true;
}

//bool prime[10000005];

//vector<ll> //prino;
//vector<int>	noof[10000005];
/*
void pre()
{	prime[0]=prime[1]=true;
	for(ll i=2;i<=10000000;i++)
	{	if(!prime[i])
		{	noof[i].pb(i);

			for(ll j=2*i;j<=10000000;j+=i)
			{	prime[j]=true;
				noof[j].pb(i);

			}
		}
	}

}*/
const int N=30010;
int dp[N][800];
int OFF=0;
int cnt[N];

int n,d;
int solve(int index,int len)
{	if(len<0)return 0;
	if(len>N)return 0;
	if(index>N)return 0;

	if(dp[index][len-OFF+246]!=-1)return dp[index][len-OFF+246];
int temp=0;

	if(len>=2)
	{	temp=cnt[index]+solve(index+len,len);
		temp=max(temp,cnt[index]+solve(index+len-1,len-1));
		temp=max(temp,cnt[index]+solve(index+len+1,len+1));
	}
	else	if(len>1)
		{	temp=cnt[index]+solve(index+len,len);
		//temp=max(temp,cnt[index]+solve(index+len-1,len-1));
			temp=max(temp,cnt[index]+solve(index+len+1,len+1));
		}
	dp[index][len-OFF+246]=temp;
	return temp;
}

int main()
{	cin>>n>>d;
	OFF=d;
	memset(dp,-1,sizeof dp);

	rep(i,n)
	{	int x;
		cin>>x;
		cnt[x]++;
	}

	int ans=cnt[0]+solve(d,d);
	cout<<ans<<endl;
	hoga;

}


#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e4+5,M=320;
int f[N][M+5<<1];
int a[N];int n,m;
inline void read(int&x){
	char c;
	for(c=getchar();!isdigit(c);c=getchar());
	for(x=0;isdigit(c);c=getchar())x=x*10+c-'0';
}
int main(){
	int ans=0,mx=0,x;read(n);read(m);
	for(int i=1;i<=n;++i){read(x);++a[x];mx=max(mx,x);}
	memset(f,-10,sizeof f);f[m][M]=a[m];ans=a[m];
	for(int i=m+1;i<=mx;++i)
		for(int j=-320;j<=320;++j){
			if(0<m+j&&m+j<=i)
				f[i][M+j]=max(f[i-m-j][M+j],max(f[i-m-j][M+j-1],f[i-m-j][M+j+1]))+a[i];
			ans=max(ans,f[i][M+j]);
		}
	printf("%d",ans);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int f[30002][1000],v[30002],n,d;
inline bool judge(int a,int b){
    if(b-500+d<1) return false;
    if(a+(b-500+d)>30000) return false;
    return true;
}
int dfs(int k,int p){
    if(f[k][p]!=-1) return f[k][p];
    f[k][p]=0;int ans=0;
    if(judge(k,p-1)) ans=max(ans,dfs(k+(p-1-500+d),p-1));
    if(judge(k,p)) ans=max(ans,dfs(k+(p-500+d),p));
    if(judge(k,p+1)) ans=max(ans,dfs(k+(p+1-500+d),p+1));
    return f[k][p]=ans+v[k];
}

int main(){
    scanf("%d%d",&n,&d);
    for(int i=1;i<=n;i++){
        int a;scanf("%d",&a);
        v[a]++;
    }memset(f,-1,sizeof(f));
    printf("%d",dfs(d,500));
    return 0;
}


/*
	I'm jump king!!
*/
#include<bits/stdc++.h>
using namespace std;

#define _ =read()
inline int read(){
	int r=0,w=1;
	char ch=getchar();
	while(ch>'9'||ch<'0'){ if(ch=='-') w=-1;ch=getchar(); }
	while(ch>='0'&&ch<='9'){ r=r*10+ch-'0'; ch=getchar(); }
	return r*w;
}

int n;
int jump;
int d;
int k[300010];
int now;
int a;
int f[101010];
int maxn=-10100101;
int main(){
	n _;
	d _;

	for(int i=1;i<=n;i++){
		 a _;
		 f[a]++;
		 maxn=max(a,maxn);
	}
	jump=d;
	int ans=0;
	for(int i=d;i<=maxn;i++){
		if(f[i-jump]>f[i-jump+1]&&f[i-jump]>f[i-jump-1]){
			f[i]+=f[i-jump];
		}
		if(jump!=1&&f[i-jump+1]>f[i-jump]&&f[i-jump+1]>f[i-jump-1]){
			f[i]+=f[i-jump+1];
			jump--;
		}
		if(f[i-jump-1]>f[i-jump]&&f[i-jump-1]>f[i-jump+1]){
			f[i]+=f[i-jump-1];
			jump++;
		}

		now=i;
		ans=max(ans,f[i]);
	}
	cout<<ans;
//	for(int i=1;i<=now;i++){
//		cout<<f[i];
//	}
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
int a[30003],f[30003][501];
int main()
{
	int n,d,ans = 0;
	scanf("%d%d",&n,&d);
	memset(f,-1,sizeof(f));
	int maxx = 0;
	for(int i = 1; i <= n; i++)
	{
		int x;
		scanf("%d",&x);
		a[x]++;
		maxx = max(maxx,x);
	}
	f[d][250] = a[d];
	for(int i = d; i <= maxx; i++)
	{
		for(int j = 0; j <= 500; j++)
		{
			if(f[i][j] != -1)
			{
				ans = max(f[i][j],ans);
				int st = j - 250 + d;
				if(i + st <= maxx)
				{
					f[i + st][j] = max(f[i + st][j],f[i][j] + a[i + st]);
				}
				if(st - 1 > 0 && i + st - 1 <= maxx)
				{
					f[i + st - 1][j - 1] = max(f[i + st - 1][j - 1],
					f[i][j] + a[i + st - 1]);
				}
				if(i + st + 1 <= maxx)
				{
					f[i + st + 1][j + 1] = max(f[i + st + 1][j + 1],
					f[i][j] + a[i + st + 1]);
				}
			}
		}
	}
	printf("%d",ans);
	return 0;
}


//In The Name of Beauty
//Go for 9
#include <bits/stdc++.h>

using namespace std;

typedef int ll;
typedef vector<ll> vll;
#define IB std::ios::sync_with_stdio(0);
#define pb(x) push_back(x);
#define mp(x,y) make_pair(x,y)
#define pll pair<ll,ll>
#define F first
#define S second
ll const MAXN = 3.3e4 + 8;
ll const ZIAD = 5e2 + 8;
ll const delta = 1000000007;

ll dp[MAXN][ZIAD];
bool mark[MAXN][ZIAD];
ll a[MAXN];
ll sz;

ll solve(ll n,ll d)
{
    if(n > sz || d == 0)return 0;
    if(mark[n][d])return dp[n][d];
    dp[n][d] = a[n] + max(solve(n + d - 1,d - 1),max(solve(n + d,d),solve(n + d + 1,d + 1)));
    mark[n][d] = 1;
    return dp[n][d];
}

int main()
{
    IB;
    cin.tie(0);
    cout.tie(0);
    ll n , d;
    cin >> n >> d;
    ll t;
    for(ll i = 1;i <= n;i++)
    {
        cin >> t;
        sz = max(sz,t);
        a[t]++;
    }
    cout << solve(d,d);
    return 0;
}
//Written by M_H_H_7


//In The Name of Beauty
//Go for 9
#include <bits/stdc++.h>

using namespace std;

typedef int ll;
typedef vector<ll> vll;
#define IB std::ios::sync_with_stdio(0);
#define pb(x) push_back(x);
#define mp(x,y) make_pair(x,y)
#define pll pair<ll,ll>
#define F first
#define S second
ll const MAXN = 3e4 + 8;
ll const ZIAD = 5e2 + 8;
ll const delta = 1000000007;

ll dp[MAXN][ZIAD];
bool mark[MAXN][ZIAD];
ll a[MAXN];
ll sz;

ll solve(ll n,ll d)
{
    if(n > sz || d == 0)return 0;
    if(mark[n][d])return dp[n][d];
    dp[n][d] = a[n] + max(solve(n + d - 1,d - 1),max(solve(n + d,d),solve(n + d + 1,d + 1)));
    mark[n][d] = 1;
    return dp[n][d];
}

int main()
{
    IB;
    cin.tie(0);
    cout.tie(0);
    ll n , d;
    cin >> n >> d;
    ll t;
    for(ll i = 1;i <= n;i++)
    {
        cin >> t;
        sz = max(sz,t);
        a[t]++;
    }
    cout << solve(d,d);
    return 0;
}
//Written by M_H_H_7


//In The Name of Beauty
//Go for 9
#include <bits/stdc++.h>

using namespace std;

typedef int ll;
typedef vector<ll> vll;
#define IB std::ios::sync_with_stdio(0);
#define pb(x) push_back(x);
#define mp(x,y) make_pair(x,y)
#define pll pair<ll,ll>
#define F first
#define S second
ll const MAXN = 3e4 + 2;
ll const ZIAD = 5e2 + 2;
ll const delta = 1000000007;

ll dp[MAXN][ZIAD];
bool mark[MAXN][ZIAD];
ll a[MAXN];
ll sz;

ll solve(ll n,ll d)
{
    if(n > sz || d == 0)return 0;
    if(mark[n][d])return dp[n][d];
    dp[n][d] = a[n] + max(solve(n + d - 1,d - 1),max(solve(n + d,d),solve(n + d + 1,d + 1)));
    mark[n][d] = 1;
    return dp[n][d];
}

int main()
{
    IB;
    cin.tie(0);
    cout.tie(0);
    ll n , d;
    cin >> n >> d;
    ll t;
    for(ll i = 1;i <= n;i++)
    {
        cin >> t;
        sz = max(sz,t);
        a[t]++;
    }
    cout << solve(d,d);
    return 0;
}
//Written by M_H_H_7


//In The Name of Beauty
//Go for 9
#include <bits/stdc++.h>

using namespace std;

typedef int ll;
typedef vector<ll> vll;
#define IB std::ios::sync_with_stdio(0);
#define pb(x) push_back(x);
#define mp(x,y) make_pair(x,y)
#define pll pair<ll,ll>
#define F first
#define S second
ll const MAXN = 3e5 + 2;
ll const ZIAD = 5e2 + 2;
ll const delta = 1000000007;

ll dp[MAXN][ZIAD];
bool mark[MAXN][ZIAD];
ll a[MAXN];
ll sz;

ll solve(ll n,ll d)
{
    if(n > sz || d == 0)return 0;
    if(mark[n][d])return dp[n][d];
    dp[n][d] = a[n] + max(solve(n + d - 1,d - 1),max(solve(n + d,d),solve(n + d + 1,d + 1)));
    mark[n][d] = 1;
    return dp[n][d];
}

int main()
{
    IB;
    cin.tie(0);
    cout.tie(0);
    ll n , d;
    cin >> n >> d;
    ll t;
    for(ll i = 1;i <= n;i++)
    {
        cin >> t;
        sz = max(sz,t);
        a[t]++;
    }
    cout << solve(d,d);
    return 0;
}
//Written by M_H_H_7


//In The Name of Beauty
//Go for 9
#include <bits/stdc++.h>

using namespace std;

typedef int ll;
typedef vector<ll> vll;
#define IB std::ios::sync_with_stdio(0);
#define pb(x) push_back(x);
#define mp(x,y) make_pair(x,y)
#define pll pair<ll,ll>
#define F first
#define S second
ll const MAXN = 3e5 + 8;
ll const ZIAD = 5e2 + 8;
ll const delta = 1000000007;

ll dp[MAXN][ZIAD];
bool mark[MAXN][ZIAD];
ll a[MAXN];
ll sz;

ll solve(ll n,ll d)
{
    if(n > sz || d == 0)return 0;
    if(mark[n][d])return dp[n][d];
    dp[n][d] = a[n] + max(solve(n + d - 1,d - 1),max(solve(n + d,d),solve(n + d + 1,d + 1)));
    mark[n][d] = 1;
    return dp[n][d];
}

int main()
{
    IB;
    cin.tie(0);
    cout.tie(0);
    ll n , d;
    cin >> n >> d;
    ll t;
    for(ll i = 1;i <= n;i++)
    {
        cin >> t;
        sz = max(sz,t);
        a[t]++;
    }
    cout << solve(d,d);
    return 0;
}
//Written by M_H_H_7


#include <bits/stdc++.h>
using namespace std;
typedef int num;

num ISLAND_CT = 30001;

int main() {
	num N, D;
	cin >> N >> D;
	vector<num> gems(ISLAND_CT, 0);
	for (num n = 1; n <= N; ++n) {
		num pos;
		cin >> pos;
		++gems[pos];
	}
	// cout << "input finished" << endl;
	vector<map<num, num>> dp(ISLAND_CT); // num = ankunftslänge, num = diamanten gebracht.
	num max_el = 0;
	dp[D][D] = gems[D];
	max_el = gems[D];
	for (num n = D; n < ISLAND_CT; ++n) {
		for (auto entry: dp[n]) {
			num speed = entry.first;
			num gems_now = entry.second;
			for (num change = -1; change < 2; ++change) {
				if (speed+change > 0 && n+speed+change < ISLAND_CT) {
					auto& new_pos = dp[n+speed+change];
					num new_gems = gems_now + gems[n+speed+change];
					if (new_pos.find(speed+change) == new_pos.end()) {
						new_pos[speed+change] = new_gems;
					}
					new_pos[speed+change] = max (new_pos[speed+change], new_gems);
					max_el = max (new_pos[speed+change], max_el);
				}
			}
		}
	}
	cout << max_el << endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long num;

num ISLAND_CT = 30001;

int main() {
	num N, D;
	cin >> N >> D;
	vector<num> gems(ISLAND_CT, 0);
	for (num n = 1; n <= N; ++n) {
		num pos;
		cin >> pos;
		++gems[pos];
	}
	// cout << "input finished" << endl;
	vector<unordered_map<num, num>> dp(ISLAND_CT); // num = ankunftslänge, num = diamanten gebracht.
	num max_el = 0;
	dp[D][D] = gems[D];
	max_el = gems[D];
	for (num n = D; n < ISLAND_CT; ++n) {
		for (auto entry: dp[n]) {
			num speed = entry.first;
			num gems_now = entry.second;
			for (num change = -1; change < 2; ++change) {
				if (speed+change > 0 && n+speed+change < ISLAND_CT) {
					auto& new_pos = dp[n+speed+change];
					num new_gems = gems_now + gems[n+speed+change];
					if (new_pos.find(speed+change) == new_pos.end()) {
						new_pos[speed+change] = new_gems;
					}
					new_pos[speed+change] = max (new_pos[speed+change], new_gems);
					max_el = max (new_pos[speed+change], max_el);
				}
			}
		}
	}
	cout << max_el << endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef int num;

num ISLAND_CT = 30001;

int main() {
	num N, D;
	cin >> N >> D;
	vector<num> gems(ISLAND_CT, 0);
	for (num n = 1; n <= N; ++n) {
		num pos;
		cin >> pos;
		++gems[pos];
	}
	// cout << "input finished" << endl;
	vector<vector<num>> dp(ISLAND_CT, vector<num>(401, -1)); //(-200 <-> 200)
	num max_el = 0;
	max_el = dp[D][200] = gems[D];
	for (num n = D; n < ISLAND_CT; ++n) {
		for (num speed = 0; speed < dp[n].size(); ++speed) {
			num gems_now = dp[n][speed];
			num speed_now = D + (speed - 200);
			if (gems_now == -1) {
				continue;
			}
			for (num change = -1; change < 2; ++change) {
				if (speed_now+change > 0 && n+speed_now+change < ISLAND_CT) {
					num new_speed = speed+change;
					num new_idx = n+speed_now+change;
					num new_gems = gems_now + gems[new_idx];
					dp[new_idx][new_speed] = max (dp[new_idx][new_speed], new_gems);
					max_el = max (dp[new_idx][new_speed], max_el);
				}
			}
		}
	}
	cout << max_el << endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef int num;

num ISLAND_CT = 30001;

int main() {
	num N, D;
	cin >> N >> D;
	vector<num> gems(ISLAND_CT, 0);
	for (num n = 1; n <= N; ++n) {
		num pos;
		cin >> pos;
		++gems[pos];
	}
	// cout << "input finished" << endl;
	vector<vector<num>> dp(ISLAND_CT, vector<num>(801, -1)); //(-200 <-> 200)
	num max_el = 0;
	max_el = dp[D][400] = gems[D];
	for (num n = D; n < ISLAND_CT; ++n) {
		for (num speed = 0; speed < dp[n].size(); ++speed) {
			num gems_now = dp[n][speed];
			num speed_now = D + (speed - 400);
			if (gems_now == -1) {
				continue;
			}
			for (num change = -1; change < 2; ++change) {
				if (speed_now+change > 0 && n+speed_now+change < ISLAND_CT) {
					num new_speed = speed+change;
					num new_idx = n+speed_now+change;
					num new_gems = gems_now + gems[new_idx];
					dp[new_idx][new_speed] = max (dp[new_idx][new_speed], new_gems);
					max_el = max (dp[new_idx][new_speed], max_el);
				}
			}
		}
	}
	cout << max_el << endl;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#define IO std::ios::sync_with_stdio(false)
#define ll long long
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define per(i, l, r) for (int i = l; i >= r; i--)
#define mset(s, _) memset(s, _, sizeof(s))
#define pb push_back
#define pii pair <int, int>
#define pdd pair <double, double>
#define mp(a, b) make_pair(a, b)
#define INF 0x3f3f3f3f
using namespace std;
inline int read() {
    int x = 0, neg = 1; char op = getchar();
    while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
    while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
    return neg * x;
}
inline void print(int x) {
    if (x < 0) { putchar('-'); x = -x; }
    if (x >= 10) print(x / 10);
    putchar(x % 10 + '0');
}

int mp[30007];
int dp[30007][507];

int main() {
    ios::sync_with_stdio(false);
    int ans = 0, temp, n, d, next;
    memset(mp, 0, sizeof(mp));
    memset(dp, -1, sizeof(dp));
    cin >> n >> d;

    for (int i = 0; i < n; ++i) {
        cin >> temp;
        ++mp[temp];
    }
    dp[d][250] = mp[d];
    for (int x = d; x <= 30000; ++x) {
        for (int y = 0; y <= 500; ++y) {
            next = x - d - y + 250;
            if (next < 0 || next >= x) continue;
            for (int i = -1; i <= 1; ++i) {
                if(dp[next][y + i] != -1 && d + y + i > 0)
                dp[x][y] = max(dp[x][y], dp[next][y + i] + mp[x]);
            }
            ans = max(ans, dp[x][y]);
        }
    }

    cout << ans << endl;
    return 0;

}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#define IO std::ios::sync_with_stdio(false)
#define ll long long
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define per(i, l, r) for (int i = l; i >= r; i--)
#define mset(s, _) memset(s, _, sizeof(s))
#define pb push_back
#define pii pair <int, int>
#define pdd pair <double, double>
#define mp(a, b) make_pair(a, b)
#define INF 0x3f3f3f3f
using namespace std;
inline int read() {
    int x = 0, neg = 1; char op = getchar();
    while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
    while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
    return neg * x;
}
inline void print(int x) {
    if (x < 0) { putchar('-'); x = -x; }
    if (x >= 10) print(x / 10);
    putchar(x % 10 + '0');
}

int mp[30007];
int dp[30007][507];

int main() {
    ios::sync_with_stdio(false);
    int ans, temp, n, d, next;
    memset(mp, 0, sizeof(mp));
    memset(dp, -1, sizeof(dp));
    cin >> n >> d;

    for (int i = 0; i < n; ++i) {
        cin >> temp;
        ++mp[temp];
    }
    dp[d][250] = mp[d];
    for (int x = d; x <= 30000; ++x) {
        for (int y = 1; y <= 500; ++y) {
            next = x - d - y + 250;
            if (next < 0 || next >= x) continue;
            for (int i = -1; i <= 1; ++i) {
                if(dp[next][y + i] != -1 && d + y + i > 0)
                dp[x][y] = max(dp[x][y], dp[next][y + i] + mp[x]);
            }
            ans = max(ans, dp[x][y]);
        }
    }

    cout << ans << endl;
    return 0;

}


// In The Name Of God
#include<bits/stdc++.h>
//17:40
using namespace std;
const int MAXN=30000 + 100;
map< int , int > s[MAXN];
map< int , int >::iterator it;
int n,d,p[MAXN],res;

inline void smax( int& a , int b ) {
	a = max( a , b );
}

int main()
{
	cin >> n >> d ;
	for(int i=1,x;i<=n;i++)
	{
		cin >> x ;
		p[x]++;
	}
	s[d][d]=0;
	for(int i=1;i<=30000;i++)
	{
		it=s[i].begin();
		for(;it!=s[i].end();it++)
		{
			int r=(*it).first,t=(*it).second;

			if( i + r - 1 > 30000 ) break;
			smax(s[i+r+1][r+1], t+p[i]);
			res=max(res,s[i+r+1][r+1]);

			smax(s[i+r][r], t+p[i]);
			res=max(res,s[i+r][r]);

			if( r - 1 > 0 ) {
				smax( s[i+r-1][r-1], t+p[i]);
				res=max(res,s[i+r-1][r-1]);
			}

			//cout << i << endl ;
		}
	}
	cout << res << endl;
	return 0;
}


// In The Name Of God
#include<bits/stdc++.h>
//17:40
using namespace std;
const int MAXN=30000 + 100;
const int MAXK=2014;
int s[MAXN][MAXK];
int n,d,p[MAXN],res;

inline void smax( int& a , int b ) {
	a = max( a , b );
}

int main()
{
	cin >> n >> d ;
	for(int i=1,x;i<=n;i++)
	{
		cin >> x ;
		p[x]++;
	}
	memset( s , -100 , sizeof s );
//	cerr << s[0][0] << endl;
	s[d][1000] = 0;
	for(int i=1;i<=30000;i++)
	{
		for( int r = max( 1 , d - 1000 ) ; r < d + 1000 ; r++ ) {
			int t = s[i][r - d + 1000];

			smax( res , t + p[i] );

			if( i + r - 1 > 30010 ) break;
			smax(s[i+r+1][r+1  -d+1000], t+p[i]);

			smax(s[i+r][r -d+1000], t+p[i]);

			if( r - 1 > 0 ) {
				smax( s[i+r-1][r-1  -d+1000], t+p[i]);
			}

			//cout << i << endl ;
		}
	}
	cout << res << endl;
	return 0;
}


// In The Name Of God
#include<bits/stdc++.h>
//17:40
using namespace std;
const int MAXN=30000 + 100;
const int MAXK=1014;
int s[MAXN][MAXK];
int n,d,p[MAXN],res;

inline void smax( int& a , int b ) {
	a = max( a , b );
}

int main()
{
	cin >> n >> d ;
	for(int i=1,x;i<=n;i++)
	{
		cin >> x ;
		p[x]++;
	}
	memset( s , -100 , sizeof s );
//	cerr << s[0][0] << endl;
	s[d][500] = 0;
	for(int i=1;i<=30000;i++)
	{
		for( int r = max( 1 , d - 500 ) ; r < d + 500 ; r++ ) {
			int t = s[i][r - d + 500];

			smax( res , t + p[i] );

			if( i + r - 1 > 30010 ) continue;
			smax(s[i+r+1][r+1  -d+500], t+p[i]);

			smax(s[i+r][r -d+500], t+p[i]);

			if( r - 1 > 0 ) {
				smax( s[i+r-1][r-1  -d+500], t+p[i]);
			}

			//cout << i << endl ;
		}
	}
	cout << res << endl;
	return 0;
}


// In The Name Of God
#include<bits/stdc++.h>
//17:40
using namespace std;
const int MAXN=30000 + 100;
const int MAXK=2014;
int s[MAXN][MAXK];
int n,d,p[MAXN],res;

inline void smax( int& a , int b ) {
	a = max( a , b );
}

int main()
{
	cin >> n >> d ;
	for(int i=1,x;i<=n;i++)
	{
		cin >> x ;
		p[x]++;
	}
	memset( s , -100 , sizeof s );
//	cerr << s[0][0] << endl;
	s[d][1000] = 0;
	for(int i=1;i<=30000;i++)
	{
		for( int r = max( 1 , d - 1000 ) ; r < d + 1000 ; r++ ) {
			int t = s[i][r - d + 1000];

			smax( res , t + p[i] );

			if( i + r - 1 > 30010 ) continue;
			smax(s[i+r+1][r+1  -d+1000], t+p[i]);

			smax(s[i+r][r -d+1000], t+p[i]);

			if( r - 1 > 0 ) {
				smax( s[i+r-1][r-1  -d+1000], t+p[i]);
			}

			//cout << i << endl ;
		}
	}
	cout << res << endl;
	return 0;
}


// In The Name Of God
#include<bits/stdc++.h>
//17:40
using namespace std;
const int MAXN=60022;
map< int , int > s[MAXN];
map< int , int >::iterator it;
int n,d,p[MAXN],res;

inline void smax( int& a , int b ) {
	a = max( a , b );
}

int main()
{
	cin >> n >> d ;
	for(int i=1,x;i<=n;i++)
	{
		cin >> x ;
		p[x]++;
	}
	s[d][d]=0;
	for(int i=1;i<=30000;i++)
	{
		it=s[i].begin();
		for(;it!=s[i].end();it++)
		{
			int r=(*it).first,t=(*it).second;

			smax(s[i+r+1][r+1], t+p[i]);
			res=max(res,s[i+r+1][r+1]);

			smax(s[i+r][r], t+p[i]);
			res=max(res,s[i+r][r]);

			if( r - 1 > 0 ) {
				smax( s[i+r-1][r-1], t+p[i]);
				res=max(res,s[i+r-1][r-1]);
			}

			//cout << i << endl ;
		}
	}
	cout << res << endl;
	return 0;
}


// In The Name Of God
#include<bits/stdc++.h>
//17:40
using namespace std;
const int MAXN=30000 + 100;
unordered_map< int , int > s[MAXN];
unordered_map< int , int >::iterator it;
int n,d,p[MAXN],res;

inline void smax( int& a , int b ) {
	a = max( a , b );
}

int main()
{
	cin >> n >> d ;
	for(int i=1,x;i<=n;i++)
	{
		cin >> x ;
		p[x]++;
	}
	s[d][d]=0;
	for(int i=1;i<=30000;i++)
	{
		it=s[i].begin();
		for(;it!=s[i].end();it++)
		{
			int r=(*it).first,t=(*it).second;

			if( i + r - 1 > 30000 ) continue;
			smax(s[i+r+1][r+1], t+p[i]);
			res=max(res,s[i+r+1][r+1]);

			smax(s[i+r][r], t+p[i]);
			res=max(res,s[i+r][r]);

			if( r - 1 > 0 ) {
				smax( s[i+r-1][r-1], t+p[i]);
				res=max(res,s[i+r-1][r-1]);
			}

			//cout << i << endl ;
		}
	}
	cout << res << endl;
	return 0;
}


// In The Name Of God
#include<bits/stdc++.h>
//17:40
using namespace std;
const int MAXN=30000 + 100;
const int MAXK=2014;
int s[MAXN][MAXK];
int n,d,p[MAXN],res;

inline void smax( int& a , int b ) {
	a = max( a , b );
}

int main()
{
	cin >> n >> d ;
	for(int i=1,x;i<=n;i++)
	{
		cin >> x ;
		p[x]++;
	}
	memset( s , -100 , sizeof s );
//	cerr << s[0][0] << endl;
	s[d][1000] = 0;
	for(int i=1;i<=30000;i++)
	{
		for( int r = max( 1 , d - 1000 ) ; r < d + 1000 ; r++ ) {
			int t = s[i][r - d + 1000];

			smax( res , t + p[i] );

			if( i + r - 1 > 30000 ) break;
			smax(s[i+r+1][r+1  -d+1000], t+p[i]);

			smax(s[i+r][r -d+1000], t+p[i]);

			if( r - 1 > 0 ) {
				smax( s[i+r-1][r-1  -d+1000], t+p[i]);
			}

			//cout << i << endl ;
		}
	}
	cout << res << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define INF 2000000000ll
#define SIZE 100000ll
#define pb push_back
//#define fin cin
int m[31000];
int dp[30010][500];
int mark[30010][500];
int n,d;
void f(int x,int k)
{
    int kk=k-d+250;
    if(mark[x][kk]) return;
    mark[x][kk]=1;
    if(k==1)
    {
        if(x+k<=30000)
        {
            f(x+k,k);
            dp[x][kk]=max(dp[x+k][kk]+m[x],dp[x][kk]);
        }
        if(x+k+1<=30000)
        {
            f(x+k+1,k+1);
            dp[x][kk]=max(dp[x+k+1][kk+1]+m[x],dp[x][kk]);
        }
    }else
    {
        if(x+k<=30000)
        {
            f(x+k,k);
            dp[x][kk]=max(dp[x+k][kk]+m[x],dp[x][kk]);
        }
        if(x+k+1<=30000)
        {
            f(x+k+1,k+1);
            dp[x][kk]=max(dp[x+k+1][kk+1]+m[x],dp[x][kk]);
        }
        if(x+k-1<=30000)
        {
            f(x+k-1,k-1);
            dp[x][kk]=max(dp[x+k-1][kk-1]+m[x],dp[x][kk]);
        }
    }
}
int32_t main()
{
    ifstream fin("input.txt",ios::in);
    ios_base::sync_with_stdio(false);
    cout<<setprecision(10);
    cin>>n>>d;
    while(n--)
    {
        int x;
        cin>>x;
        m[x]++;
    }
    f(d,d);
    cout<<dp[d][250]+m[0]<<endl;
    cout<<endl;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define INF 2000000000ll
#define SIZE 100000ll
#define pb push_back
//#define fin cin
int m[31000];
int dp[31010][500];
int mark[31010][500];
int n,d;
void f(int x,int k)
{
    int kk=k-d+250;
    if(mark[x][kk]) return;
    mark[x][kk]=1;
    if(k==1)
    {
        if(x+k<=31000)
        {
            f(x+k,k);
            dp[x][kk]=max(dp[x+k][kk]+m[x],dp[x][kk]);
        }
        if(x+k+1<=31000)
        {
            f(x+k+1,k+1);
            dp[x][kk]=max(dp[x+k+1][kk+1]+m[x],dp[x][kk]);
        }
    }else
    {
        if(x+k<=31000)
        {
            f(x+k,k);
            dp[x][kk]=max(dp[x+k][kk]+m[x],dp[x][kk]);
        }
        if(x+k+1<=31000)
        {
            f(x+k+1,k+1);
            dp[x][kk]=max(dp[x+k+1][kk+1]+m[x],dp[x][kk]);
        }
        if(x+k-1<=31000)
        {
            f(x+k-1,k-1);
            dp[x][kk]=max(dp[x+k-1][kk-1]+m[x],dp[x][kk]);
        }
    }
}
int32_t main()
{
    ifstream fin("input.txt",ios::in);
    ios_base::sync_with_stdio(false);
    cout<<setprecision(10);
    cin>>n>>d;
    while(n--)
    {
        int x;
        cin>>x;
        m[x]++;
    }
    f(d,d);
    cout<<dp[d][250]+m[0]<<endl;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define INF 2000000000ll
#define SIZE 100000ll
#define pb push_back
//#define fin cin
int m[31000];
int dp[31010][500];
int mark[31010][500];
int n,d;
int f(int x,int k)
{
    int kk=k-d+250;
    if(mark[x][kk]) return dp[x][kk];
    if(x>30000) return 0;
    mark[x][kk]=1;
    if(k==1)
    {
        dp[x][kk]=max(f(x+k,k)+m[x],dp[x][kk]);
        dp[x][kk]=max(f(x+k+1,k+1)+m[x],dp[x][kk]);
    }else
    {
        dp[x][kk]=max(f(x+k,k)+m[x],dp[x][kk]);
        dp[x][kk]=max(f(x+k+1,k+1)+m[x],dp[x][kk]);
        dp[x][kk]=max(f(x+k-1,k-1)+m[x],dp[x][kk]);
    }
    return dp[x][kk];
}
int32_t main()
{
    ifstream fin("input.txt",ios::in);
    ios_base::sync_with_stdio(false);
    cout<<setprecision(10);
    cin>>n>>d;
    while(n--)
    {
        int x;
        cin>>x;
        m[x]++;
    }
    f(d,d);
    cout<<dp[d][250]+m[0]<<endl;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define INF 2000000000ll
#define SIZE 100000ll
#define pb push_back
//#define fin cin
int m[31000];
int dp[30010][500];
int mark[30010][500];
int n,d;
void f(int x,int k)
{
    int kk=k-d+250;
    if(mark[x][kk]) return;
    mark[x][kk]=1;
    if(k==1)
    {
        if(x+k<=30000)
        {
            f(x+k,k);
            dp[x][kk]=max(dp[x+k][kk]+m[x],dp[x][kk]);
        }
        if(x+k+1<=30000)
        {
            f(x+k+1,k+1);
            dp[x][kk]=max(dp[x+k+1][kk+1]+m[x],dp[x][kk]);
        }
    }else
    {
        if(x+k<=30000)
        {
            f(x+k,k);
            dp[x][kk]=max(dp[x+k][kk]+m[x],dp[x][kk]);
        }
        if(x+k+1<=30000)
        {
            f(x+k+1,k+1);
            dp[x][kk]=max(dp[x+k+1][kk+1]+m[x],dp[x][kk]);
        }
        if(x+k-1<=30000)
        {
            f(x+k-1,k-1);
            dp[x][kk]=max(dp[x+k-1][kk-1]+m[x],dp[x][kk]);
        }
    }
}
int32_t main()
{
    ifstream fin("input.txt",ios::in);
    ios_base::sync_with_stdio(false);
    cout<<setprecision(10);
    cin>>n>>d;
    while(n--)
    {
        int x;
        cin>>x;
        m[x]++;
    }
    f(d,d);
    cout<<dp[d][250]<<endl;
    cout<<endl;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define INF 2000000000ll
#define SIZE 100000ll
#define pb push_back
//#define fin cin
int m[31000];
int dp[31010][500];
int mark[31010][500];
int n,d;
int f(int x,int k)
{
    int kk=k-d+250;
    if(mark[x][kk]||x>30000) return 0;
    mark[x][kk]=1;
    if(k==1)
    {
        dp[x][kk]=max(f(x+k,k)+m[x],dp[x][kk]);
        dp[x][kk]=max(f(x+k+1,k+1)+m[x],dp[x][kk]);
    }else
    {
        dp[x][kk]=max(f(x+k,k)+m[x],dp[x][kk]);
        dp[x][kk]=max(f(x+k+1,k+1)+m[x],dp[x][kk]);
        dp[x][kk]=max(f(x+k-1,k-1)+m[x],dp[x][kk]);
    }
}
int32_t main()
{
    ifstream fin("input.txt",ios::in);
    ios_base::sync_with_stdio(false);
    cout<<setprecision(10);
    cin>>n>>d;
    while(n--)
    {
        int x;
        cin>>x;
        m[x]++;
    }
    f(d,d);
    cout<<dp[d][250]+m[0]<<endl;
}


#include <iostream>
#include <set>
#include <map>

#define LAST_INDEX 30000
#define SENTINEL -17
using namespace std;

int n,d;
set<int> ansSet;
map<pair<int,int>,int> ansMap;
int posNstep[LAST_INDEX+1][500];
int gems[LAST_INDEX+1];

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}

int dfsSavingAnswers(int position, int stepSize){
  if(position > LAST_INDEX){
    return 0;
  }

  pair<int,int> cur = {position,stepSize};
  if(ansMap.count(cur) != 0){
    return ansMap[cur];
  }

  if(stepSize == 1){
    ansMap[cur] = max(dfsSavingAnswers(position+stepSize+1, stepSize+1),
		      dfsSavingAnswers(position+stepSize, stepSize)) + gems[position];
    return ansMap[cur];
  }
  else{
    ansMap[cur] = threeMax(dfsSavingAnswers(position+stepSize+1, stepSize+1),
			 dfsSavingAnswers(position+stepSize, stepSize),
			 dfsSavingAnswers(position+stepSize-1, stepSize-1)) + gems[position];
    return ansMap[cur];
  }
}

void arrayInit(){
  for(int i=0; i<LAST_INDEX; i++)
    for(int j=1; j<500; j++)
      posNstep[i][j] = SENTINEL;
}

int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 500){
    cout<<dfsSavingAnswers(d,d)<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <iostream>
#include <set>

#define LAST_INDEX 30000
#define SENTINEL -17
using namespace std;

int n,d;
set<int> ansSet;
int posNstep[LAST_INDEX+1][500];
int gems[LAST_INDEX+1];
void dfsSavingAnswers(int position, int stepSize, int numGems){
  if(position > LAST_INDEX){
    ansSet.insert(numGems);
    return;
  }

  numGems += gems[position];
  dfsSavingAnswers(position+stepSize+1, stepSize+1, numGems);
  dfsSavingAnswers(position+stepSize, stepSize, numGems);
  if(stepSize > 1)
    dfsSavingAnswers(position+stepSize-1, stepSize-1, numGems);
}

void arrayInit(){
  for(int i=0; i<LAST_INDEX; i++)
    for(int j=1; j<500; j++)
      posNstep[i][j] = SENTINEL;
}

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}
int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 500){
    dfsSavingAnswers(d,d,0);
    set<int>::reverse_iterator it = ansSet.rbegin();
    cout<<*it<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <iostream>
#include <set>
#include <map>

#define LAST_INDEX 30000
#define SENTINEL -7
using namespace std;

int n,d;
set<int> ansSet;
map<pair<int,int>,int> ansMap;
int posNstep[LAST_INDEX+1][1000];
int gems[LAST_INDEX+1];

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}

int dfsSavingAnswers(int position, int stepSize){
  if(position > LAST_INDEX){
    return 0;
  }

  pair<int,int> cur = {position,stepSize};
  if(ansMap.count(cur) != 0){
    return ansMap[cur];
  }

  if(stepSize == 1){
    ansMap[cur] = max(dfsSavingAnswers(position+stepSize+1, stepSize+1),
		      dfsSavingAnswers(position+stepSize, stepSize)) + gems[position];
    return ansMap[cur];
  }
  else{
    ansMap[cur] = threeMax(dfsSavingAnswers(position+stepSize+1, stepSize+1),
			 dfsSavingAnswers(position+stepSize, stepSize),
			 dfsSavingAnswers(position+stepSize-1, stepSize-1)) + gems[position];
    return ansMap[cur];
  }
}

void arrayInit(){
  for(int i=0; i<=LAST_INDEX; i++)
    for(int j=1; j<1000; j++)
      posNstep[i][j] = SENTINEL;
}

int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 900){
    cout<<dfsSavingAnswers(d,d)<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <iostream>
#include <set>
#include <map>

#define LAST_INDEX 30000
#define SENTINEL -7
using namespace std;

int n,d;
set<int> ansSet;
map<pair<int,int>,int> ansMap;
int posNstep[LAST_INDEX+1][500];
int gems[LAST_INDEX+1];

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}

int dfsSavingAnswers(int position, int stepSize){
  if(position > LAST_INDEX){
    return 0;
  }

  pair<int,int> cur = {position,stepSize};
  if(ansMap.count(cur) != 0){
    return ansMap[cur];
  }

  if(stepSize == 1){
    ansMap[cur] = max(dfsSavingAnswers(position+stepSize+1, stepSize+1),
		      dfsSavingAnswers(position+stepSize, stepSize)) + gems[position];
    return ansMap[cur];
  }
  else{
    ansMap[cur] = threeMax(dfsSavingAnswers(position+stepSize+1, stepSize+1),
			 dfsSavingAnswers(position+stepSize, stepSize),
			 dfsSavingAnswers(position+stepSize-1, stepSize-1)) + gems[position];
    return ansMap[cur];
  }
}

void arrayInit(){
  for(int i=0; i<=LAST_INDEX; i++)
    for(int j=1; j<1000; j++)
      posNstep[i][j] = SENTINEL;
}

int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 700){
    cout<<dfsSavingAnswers(d,d)<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <iostream>
#include <set>

#define LAST_INDEX 30000
#define SENTINEL -17
using namespace std;

int n,d;
set<int> ansSet;
int posNstep[LAST_INDEX+1][500];
int gems[LAST_INDEX+1];
void dfsSavingAnswers(int position, int stepSize, int numGems){
  if(position > LAST_INDEX){
    ansSet.insert(numGems);
    return;
  }

  numGems += gems[position];
  dfsSavingAnswers(position+stepSize+1, stepSize+1, numGems);
  dfsSavingAnswers(position+stepSize, stepSize, numGems);
  if(stepSize > 1)
    dfsSavingAnswers(position+stepSize-1, stepSize-1, numGems);
}

void arrayInit(){
  for(int i=0; i<LAST_INDEX; i++)
    for(int j=1; j<500; j++)
      posNstep[i][j] = SENTINEL;
}

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}
int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 300){
    dfsSavingAnswers(d,d,0);
    set<int>::reverse_iterator it = ansSet.rbegin();
    cout<<*it<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <iostream>
#include <set>
#include <map>

#define LAST_INDEX 30000
#define SENTINEL -7
using namespace std;

int n,d;
set<int> ansSet;
map<pair<int,int>,int> ansMap;
int posNstep[LAST_INDEX+1][500];
int gems[LAST_INDEX+1];

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}

int dfsSavingAnswers(int position, int stepSize){
  if(position > LAST_INDEX){
    return 0;
  }

  pair<int,int> cur = {position,stepSize};
  if(ansMap.count(cur) != 0){
    return ansMap[cur];
  }

  if(stepSize == 1){
    ansMap[cur] = max(dfsSavingAnswers(position+stepSize+1, stepSize+1),
		      dfsSavingAnswers(position+stepSize, stepSize)) + gems[position];
    return ansMap[cur];
  }
  else{
    ansMap[cur] = threeMax(dfsSavingAnswers(position+stepSize+1, stepSize+1),
			 dfsSavingAnswers(position+stepSize, stepSize),
			 dfsSavingAnswers(position+stepSize-1, stepSize-1)) + gems[position];
    return ansMap[cur];
  }
}

void arrayInit(){
  for(int i=0; i<=LAST_INDEX; i++)
    for(int j=1; j<500; j++)
      posNstep[i][j] = SENTINEL;
}

int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<=LAST_INDEX; i++)
    gems[i] = 0;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 550){
    cout<<dfsSavingAnswers(d,d)<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <iostream>
#include <set>
#include <map>

#define LAST_INDEX 30000
#define SENTINEL -7
using namespace std;

int n,d;
set<int> ansSet;
map<pair<int,int>,int> ansMap;
int posNstep[LAST_INDEX+1][500];
int gems[LAST_INDEX+1];

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}

int dfsSavingAnswers(int position, int stepSize){
  if(position > LAST_INDEX){
    return 0;
  }

  pair<int,int> cur = {position,stepSize};
  if(ansMap.count(cur) != 0){
    return ansMap[cur];
  }

  if(stepSize == 1){
    ansMap[cur] = max(dfsSavingAnswers(position+stepSize+1, stepSize+1),
		      dfsSavingAnswers(position+stepSize, stepSize)) + gems[position];
    return ansMap[cur];
  }
  else{
    ansMap[cur] = threeMax(dfsSavingAnswers(position+stepSize+1, stepSize+1),
			 dfsSavingAnswers(position+stepSize, stepSize),
			 dfsSavingAnswers(position+stepSize-1, stepSize-1)) + gems[position];
    return ansMap[cur];
  }
}

void arrayInit(){
  for(int i=0; i<=LAST_INDEX; i++)
    for(int j=1; j<500; j++)
      posNstep[i][j] = SENTINEL;
}

int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 500){
    cout<<dfsSavingAnswers(d,d)<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <iostream>
#include <set>
#include <map>

#define LAST_INDEX 30000
#define SENTINEL -7
using namespace std;

int n,d;
set<int> ansSet;
map<pair<int,int>,int> ansMap;
int posNstep[LAST_INDEX+1][500];
int gems[LAST_INDEX+1];

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}

int dfsSavingAnswers(int position, int stepSize){
  if(position > LAST_INDEX){
    return 0;
  }

  pair<int,int> cur = {position,stepSize};
  if(ansMap.count(cur) != 0){
    return ansMap[cur];
  }

  if(stepSize == 1){
    ansMap[cur] = max(dfsSavingAnswers(position+stepSize+1, stepSize+1),
		      dfsSavingAnswers(position+stepSize, stepSize)) + gems[position];
    return ansMap[cur];
  }
  else{
    ansMap[cur] = threeMax(dfsSavingAnswers(position+stepSize+1, stepSize+1),
			 dfsSavingAnswers(position+stepSize, stepSize),
			 dfsSavingAnswers(position+stepSize-1, stepSize-1)) + gems[position];
    return ansMap[cur];
  }
}

void arrayInit(){
  for(int i=0; i<LAST_INDEX; i++)
    for(int j=1; j<500; j++)
      posNstep[i][j] = SENTINEL;
}

int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 500){
    cout<<dfsSavingAnswers(d,d)<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <iostream>
#include <set>
#include <map>

#define LAST_INDEX 30000
#define SENTINEL -7
using namespace std;

int n,d;
set<int> ansSet;
map<pair<int,int>,int> ansMap;
int posNstep[LAST_INDEX+1][500];
int gems[LAST_INDEX+1];

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}

int dfsSavingAnswers(int position, int stepSize){
  if(position > LAST_INDEX){
    return 0;
  }

  pair<int,int> cur = {position,stepSize};
  if(ansMap.count(cur) != 0){
    return ansMap[cur];
  }

  if(stepSize == 1){
    ansMap[cur] = max(dfsSavingAnswers(position+stepSize+1, stepSize+1),
		      dfsSavingAnswers(position+stepSize, stepSize)) + gems[position];
    return ansMap[cur];
  }
  else{
    ansMap[cur] = threeMax(dfsSavingAnswers(position+stepSize+1, stepSize+1),
			 dfsSavingAnswers(position+stepSize, stepSize),
			 dfsSavingAnswers(position+stepSize-1, stepSize-1)) + gems[position];
    return ansMap[cur];
  }
}

void arrayInit(){
  for(int i=0; i<=LAST_INDEX; i++)
    for(int j=1; j<500; j++)
      posNstep[i][j] = SENTINEL;
}

int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 550){
    cout<<dfsSavingAnswers(d,d)<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <iostream>
#include <set>
#include <map>

#define LAST_INDEX 30000
#define SENTINEL -7
using namespace std;

int n,d;
set<int> ansSet;
map<pair<int,int>,int> ansMap;
int posNstep[LAST_INDEX+1][500];
int gems[LAST_INDEX+1];

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}

int dfsSavingAnswers(int position, int stepSize){
  if(position > LAST_INDEX){
    return 0;
  }

  pair<int,int> cur = {position,stepSize};
  if(ansMap.count(cur) != 0){
    return ansMap[cur];
  }

  if(stepSize == 1){
    ansMap[cur] = max(dfsSavingAnswers(position+stepSize+1, stepSize+1),
		      dfsSavingAnswers(position+stepSize, stepSize)) + gems[position];
    return ansMap[cur];
  }
  else{
    ansMap[cur] = threeMax(dfsSavingAnswers(position+stepSize+1, stepSize+1),
			 dfsSavingAnswers(position+stepSize, stepSize),
			 dfsSavingAnswers(position+stepSize-1, stepSize-1)) + gems[position];
    return ansMap[cur];
  }
}

void arrayInit(){
  for(int i=0; i<=LAST_INDEX; i++)
    for(int j=1; j<500; j++)
      posNstep[i][j] = SENTINEL;
}

int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<=LAST_INDEX; i++)
    gems[i] = 0;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 700){
    cout<<dfsSavingAnswers(d,d)<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <iostream>
#include <set>
#include <map>

#define LAST_INDEX 30000
#define SENTINEL -7
using namespace std;

int n,d;
set<int> ansSet;
map<pair<int,int>,int> ansMap;
int posNstep[LAST_INDEX+1][500];
int gems[LAST_INDEX+1];

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}

int dfsSavingAnswers(int position, int stepSize){
  if(position > LAST_INDEX){
    return 0;
  }

  pair<int,int> cur = {position,stepSize};
  if(ansMap.count(cur) != 0){
    return ansMap[cur];
  }

  if(stepSize == 1){
    ansMap[cur] = max(dfsSavingAnswers(position+stepSize+1, stepSize+1),
		      dfsSavingAnswers(position+stepSize, stepSize)) + gems[position];
    return ansMap[cur];
  }
  else{
    ansMap[cur] = threeMax(dfsSavingAnswers(position+stepSize+1, stepSize+1),
			 dfsSavingAnswers(position+stepSize, stepSize),
			 dfsSavingAnswers(position+stepSize-1, stepSize-1)) + gems[position];
    return ansMap[cur];
  }
}

void arrayInit(){
  for(int i=0; i<LAST_INDEX; i++)
    for(int j=1; j<500; j++)
      posNstep[i][j] = SENTINEL;
}

int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<=LAST_INDEX; i++)
    gems[i] = 0;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 500){
    cout<<dfsSavingAnswers(d,d)<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <iostream>
#include <set>
#include <map>

#define LAST_INDEX 30000
#define SENTINEL 0
using namespace std;

int n,d;
set<int> ansSet;
map<pair<int,int>,int> ansMap;
int posNstep[LAST_INDEX+1][500];
int gems[LAST_INDEX+1];

int threeMax(int a, int b, int c){
  return max(max(a,b),c);
}

int dfsSavingAnswers(int position, int stepSize){
  if(position > LAST_INDEX){
    return 0;
  }

  pair<int,int> cur = {position,stepSize};
  if(ansMap.count(cur) != 0){
    return ansMap[cur];
  }

  if(stepSize == 1){
    ansMap[cur] = max(dfsSavingAnswers(position+stepSize+1, stepSize+1),
		      dfsSavingAnswers(position+stepSize, stepSize)) + gems[position];
    return ansMap[cur];
  }
  else{
    ansMap[cur] = threeMax(dfsSavingAnswers(position+stepSize+1, stepSize+1),
			 dfsSavingAnswers(position+stepSize, stepSize),
			 dfsSavingAnswers(position+stepSize-1, stepSize-1)) + gems[position];
    return ansMap[cur];
  }
}

void arrayInit(){
  for(int i=0; i<LAST_INDEX; i++)
    for(int j=1; j<500; j++)
      posNstep[i][j] = SENTINEL;
}

int dfsOnArray(int position, int stepSize){
  if(position > LAST_INDEX)
    return 0;
  if(posNstep[position][stepSize] != SENTINEL)
    return posNstep[position][stepSize];

  if(stepSize == 1){
    posNstep[position][stepSize] = max(dfsOnArray(position+stepSize+1,stepSize+1),
				       dfsOnArray(position+stepSize,stepSize)) + gems[position];
    return posNstep[position][stepSize];
  }
  else{
    posNstep[position][stepSize] = threeMax(dfsOnArray(position+stepSize+1,stepSize+1),
					  dfsOnArray(position+stepSize, stepSize),
					    dfsOnArray(position+stepSize-1, stepSize-1)) + gems[position];
    return posNstep[position][stepSize];
  }
}
main(){
  cin>>n>>d;
  for(int i=0; i<n; i++){
    int islandNum; cin>>islandNum;
    gems[islandNum]++;
  }

  if(d >= 500){
    cout<<dfsSavingAnswers(d,d)<<endl;
    return 0;
  }

  arrayInit();
  cout<<dfsOnArray(d,d)<<endl;

}


#include <bits/stdc++.h>
#define eb emplace_back
#define pb push_back
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define all(a) (a.begin(),a.end())

using ll = long long;
using namespace std;
template<typename... Args>
void read(Args&... args)
{((cin >> args), ...);}

template<typename... Args>
void write(Args... args)
{((cout << args << " "), ...);}

template<typename... Args>
void writeln(Args... args)
{((cout << args << " "), ...); cout << "\n";}

template<typename T>
void read(vector<T> &a)
{for (auto &ele : a) cin >> ele;}

template<typename T>
void writeln(vector<T> &a)
{for (auto &ele : a) cout << ele << ' '; cout << "\n";}

const pii dxy[] = {{ -1, 0}, {1, 0}, {0, -1}, {0, 1}};
const pii fxy[] = {{ -1, 0}, {1, 0}, {0, -1}, {0, 1}, {1, 1}, { -1, -1}, { -1, 1}, {1, -1}};

int link[55];
int len[55];

int find(int x) {
	while (x != link[x]) {
		link[x] = link[link[x]];
		x = link[x];
	}
	return x;
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);
	if (len[a] < len[b]) swap(a, b);
	link[b] = a;
	len[a] += len[b];
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	cin.tie(0); cout.tie(0);
	ios::sync_with_stdio(false);
//	int t;cin >> t;while(t--) solve();
	int n, m;
	read(n, m);
	for (int i = 1; i <= n; ++i) {
		link[i] = i;
	}
	for (int i = 1; i <= n; ++i) {
		len[i] = 1;
	}
	while (m--) {
		int a, b;
		read(a, b);
		unite(a, b);
	}
	int res = 0;
	for (int i = 1; i <= n; ++i) {
		res = max(res, len[i]);
	}
	res = pow(2, res - 1);
	writeln(res);
	return 0;
}


#include <bits/stdc++.h>
#define eb emplace_back
#define pb push_back
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define all(a) (a.begin(),a.end())

using ll = long long;
using namespace std;
template<typename... Args>
void read(Args&... args)
{((cin >> args), ...);}

template<typename... Args>
void write(Args... args)
{((cout << args << " "), ...);}

template<typename... Args>
void writeln(Args... args)
{((cout << args << " "), ...); cout << "\n";}

template<typename T>
void read(vector<T> &a)
{for (auto &ele : a) cin >> ele;}

template<typename T>
void writeln(vector<T> &a)
{for (auto &ele : a) cout << ele << ' '; cout << "\n";}

const pii dxy[] = {{ -1, 0}, {1, 0}, {0, -1}, {0, 1}};
const pii fxy[] = {{ -1, 0}, {1, 0}, {0, -1}, {0, 1}, {1, 1}, { -1, -1}, { -1, 1}, {1, -1}};

int link[55];
int len[55];

int find(int x) {
	while (x != link[x]) {
		link[x] = link[link[x]];
		x = link[x];
	}
	return x;
}

void unite(int a, int b) {
	a = find(a);
	b = find(b);
	if (a == b) return;
	if (len[a] < len[b]) swap(a, b);
	link[b] = a;
	len[a] += len[b];
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	cin.tie(0); cout.tie(0);
	ios::sync_with_stdio(false);
	//	int t;cin >> t;while(t--) solve();
	int n, m;
	read(n, m);
	for (int i = 1; i <= n; ++i) {
		link[i] = i;
	}
	for (int i = 1; i <= n; ++i) {
		len[i] = 1;
	}
	while (m--) {
		int a, b;
		read(a, b);
		unite(a, b);
	}
	ll res = 1ll << n;
	for (int i = 1; i <= n; ++i) {
		if (link[i] == i) res /= 2;
	}
	//res = pow(2, res - 1);
	writeln(res);
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
#define mp make_pair

ll parent[51], sizes[51];

ll find(ll u)
{
    return (parent[u] == u ? u : parent[u] = find(parent[u]));
}

void join(ll a, ll b)
{
    a = find(a); b = find(b);
    if(a == b) return;
    if(sizes[b] > sizes[a]) swap(a, b);
    parent[b] = a;
    sizes[a] += sizes[b];
}

int main()
{
    ios_base::sync_with_stdio(false);

    ll n, m; cin >> n >> m;
    for(ll i = 1; i <= n; i++)
        parent[i] = i;
    fill(sizes, sizes+n, 1);

    while(m--)
    {
        ll u, v; cin >> u >> v;
        join(u, v);
    }

    ll answer = 1 << n;
    for(ll i = 1; i <= n; i++)
        if(find(i) == i) answer /= 2;

    cout << answer;

    ll xyz; cin >> xyz; return 0;
}


#include <iostream>
#include <vector>
#include <string.h>
using namespace std;
const int N=55;
int n,m,x,y,vis[N];
long long int ans ;
vector <int> react[N];
int main(){
memset(vis,-1,sizeof vis);
cin>>n>>m;
ans = 1LL << n;
while(m--){
cin>>x>>y;
react[x].push_back(y);
react[y].push_back(x);
}
for(int i=1; i<= n ;i++ ) {
    vis[i]=1;
 for(int j=0;j<react[i].size();j++) {
     if(vis[react[i][j]]==1){
        ans/=2;
        break;
     }
 }
}
cout<<ans<<endl;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
#define mp make_pair

bool vis[51];
vector<int> graph[51];

int dfs(int cur, int step)
{
    if(vis[cur] == true)
        return 0;
    vis[cur] = true;

    int ans = 1;
    for(int i = 0; i < graph[cur].size(); ++i)
    {
        ans += dfs(graph[cur][i], step+1);
    }
    return ans;
}

int main()
{
    ios_base::sync_with_stdio(false);

    int n, m; cin >> n >> m;
    memset(vis, 0, sizeof vis);

    while(m--)
    {
        int u, v; cin >> u >> v;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }

    int ans = 0;
    for(int i = 1; i <= n; i++)
    {
        if(!vis[i])
            ans = max(ans, dfs(i, 0));
    }

    if(ans == n)
        --ans;

    cout << (1 << ans);

    int xyz; cin >> xyz; return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
#define mp make_pair

int parent[51], sizes[51], dangers[51];
int maxDanger = 1;

int find(int u)
{
    return (parent[u] == u ? u : parent[u] = find(parent[u]));
}

void join(int a, int b)
{
    a = find(a); b = find(b);
    if(a == b) return;
    if(sizes[b] > sizes[a]) swap(a, b);
    parent[b] = a;
    sizes[a] += sizes[b];
    dangers[a] *= 2;
    maxDanger = max(maxDanger, dangers[a]);
}

int main()
{
    ios_base::sync_with_stdio(false);

    int n, m; cin >> n >> m;
    iota(parent, parent+n, 0);
    fill(sizes, sizes+n, 1);
    fill(dangers, dangers+n, 1);

    while(m--)
    {
        int u, v; cin >> u >> v;
        join(u, v);
    }

    cout << maxDanger;

    int xyz; cin >> xyz; return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
#define mp make_pair

ll parent[51], sizes[51];

ll find(ll u)
{
    return (parent[u] == u ? u : parent[u] = find(parent[u]));
}

void join(ll a, ll b)
{
    a = find(a); b = find(b);
    if(a == b) return;
    if(sizes[b] > sizes[a]) swap(a, b);
    parent[b] = a;
    sizes[a] += sizes[b];
}

int main()
{
    ios_base::sync_with_stdio(false);

    ll n, m; cin >> n >> m;
    for(ll i = 1; i <= n; i++)
        parent[i] = i;
    fill(sizes, sizes+n, 1);

    while(m--)
    {
        ll u, v; cin >> u >> v;
        join(u, v);
    }

    ll answer = 1LL << n;
    for(ll i = 1; i <= n; i++)
        if(find(i) == i) answer /= 2;

    cout << answer;

    ll xyz; cin >> xyz; return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
#define mp make_pair

int parent[51], sizes[51];
int maxDanger = 1;

int find(int u)
{
    return (parent[u] == u ? u : parent[u] = find(parent[u]));
}

void join(int a, int b)
{
    a = find(a); b = find(b);
    if(a == b) return;
    if(sizes[b] > sizes[a]) swap(a, b);
    parent[b] = a;
    sizes[a] *= 2;
    maxDanger = max(maxDanger, sizes[a]);
}

int main()
{
    ios_base::sync_with_stdio(false);

    int n, m; cin >> n >> m;
    iota(parent, parent+n, 0);
    fill(sizes, sizes+n, 1);
    //fill(dangers, dangers+n, 1);

    while(m--)
    {
        int u, v; cin >> u >> v;
        join(u, v);
    }

    cout << maxDanger;

    int xyz; cin >> xyz; return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
#define mp make_pair

int parent[51], sizes[51], dangers[51];
int maxDanger = 1;

int find(int u)
{
    return (parent[u] == u ? u : parent[u] = find(parent[u]));
}

void join(int a, int b)
{
    a = find(a); b = find(b);
    if(a == b) return;
    if(sizes[b] > sizes[a]) swap(a, b);
    parent[b] = a;
    sizes[a] += sizes[b];
    maxDanger = max(maxDanger, sizes[a]);
}

int main()
{
    ios_base::sync_with_stdio(false);

    int n, m; cin >> n >> m;
    iota(parent, parent+n, 0);
    fill(sizes, sizes+n, 1);
    fill(dangers, dangers+n, 1);

    while(m--)
    {
        int u, v; cin >> u >> v;
        join(u, v);
    }

    cout << pow(2, maxDanger-1);

    int xyz; cin >> xyz; return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
#define mp make_pair

int parent[51], sizes[51];

int find(int u)
{
    return (parent[u] == u ? u : parent[u] = find(parent[u]));
}

void join(int a, int b)
{
    a = find(a); b = find(b);
    if(a == b) return;
    if(sizes[b] > sizes[a]) swap(a, b);
    parent[b] = a;
    sizes[a] += sizes[b];
}

int main()
{
    ios_base::sync_with_stdio(false);

    int n, m; cin >> n >> m;
    for(int i = 1; i <= n; i++)
        parent[i] = i;
    fill(sizes, sizes+n, 1);

    while(m--)
    {
        int u, v; cin >> u >> v;
        join(u, v);
    }

    int answer = 1 << n;
    for(int i = 1; i <= n; i++)
        if(find(i) == i) answer /= 2;

    cout << answer;

    int xyz; cin >> xyz; return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
#define mp make_pair

int parent[51], sizes[51];
int biggest = 1;

int find(int u)
{
    return (parent[u] == u ? u : parent[u] = find(parent[u]));
}

void join(int a, int b)
{
    a = find(a); b = find(b);
    if(a == b) return;
    if(sizes[b] > sizes[a]) swap(a, b);
    parent[b] = a;
    sizes[a] += sizes[b];
    biggest = max(biggest, sizes[a]);
}

int main()
{
    ios_base::sync_with_stdio(false);

    int n, m; cin >> n >> m;
    iota(parent, parent+n, 0);
    fill(sizes, sizes+n, 1);
    //fill(dangers, dangers+n, 1);

    while(m--)
    {
        int u, v; cin >> u >> v;
        join(u, v);
    }

    int answer = 1 << (biggest-1);
    cout << answer;

    int xyz; cin >> xyz; return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
#define mp make_pair

bool vis[51];
vector<int> graph[51];

int dfs(int cur, int step)
{
    if(vis[cur] == true)
        return 0;
    vis[cur] = true;

    int ans = 1;
    for(int i = 0; i < graph[cur].size(); ++i)
    {
        ans += dfs(graph[cur][i], step+1);
    }
    return ans;
}

int main()
{
    ios_base::sync_with_stdio(false);

    int n, m; cin >> n >> m;
    memset(vis, 0, sizeof vis);

    while(m--)
    {
        int u, v; cin >> u >> v;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }

    int ans = 0;
    for(int i = 1; i <= n; i++)
    {
        if(!vis[i])
            ans = max(ans, dfs(i, 0));
    }

    int z = n-ans;

    cout << (1 << z);

    int xyz; cin >> xyz; return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define MEMEGOD_HERE ios_base::sync_with_stdio(0),cin.tie(0);cout.tie(0);
#define cnt1br __built_popcountll();
using namespace std;

//std::setprecision(5)
	vector <ll> v(60,0);
	vector <ll> graph[60];

	void dfs(ll x)
	{
		if(!v[x])
		{
			v[x]=1;
			for(auto itr:graph[x])
				dfs(itr);
		}
	}

	int main()
	{
		MEMEGOD_HERE;

		ll t=1;
		//cin>>t;
		while(t--)
		{
			ll n,m,i,x,y;
			cin>>n>>m;
			while(m--)
			{
				cin>>x>>y;
				graph[x].pb(y);
				graph[y].pb(x);
			}
			ll co=0;
			for(i=1;i<=n;i++)
			{
				if(v[i]==0)
				{
					dfs(i);
					co++;
				}
			}

			cout<<pow(2,n-co)<<"\n";
		}
		return 0;
	}


#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define MEMEGOD_HERE ios_base::sync_with_stdio(0),cin.tie(0);cout.tie(0);
#define cnt1br __built_popcountll();

using namespace std;

//std::setprecision(5)

	//Commonly Used Global Variables
	ll i,j,flag,co=0,n,m,k,x;
	const ll N=1e6,MOD=1e9+7;
	string s;

	//Commonly Used Data_structure and STL
	vector <ll> graph[N+5000];
	vector <ll> v,res;
/*	vector<ll> Sieve(ll n)  //Highly Optimized Sieve
	{	vector <ll> primes;		bool v[200010];
		ll size=n;		memset(v,true,sizeof v);
		v[0]=v[1]=false;

		for(i=2;i<=n;)
		{	if(v[i])
			{//cout<<i<<" ";
				primes.pb(i);
				for(j=i*i;j<=n;)
				{	v[j]=false;
					if(i==2)	j+=i;
					else	j+=2*i;
				}
			}
			if(i%2==0)	 i++;
			else		 i=i+2;
		}	return primes;	}

	ll binpow(ll a,ll b,ll n)
	{
		ll res=1;
		a%=n;
		while(b)
		{
			if(b&1)
				res=(res*a)%n;
			b>>1;
			a=a*a;
		}
		return res;
	}
*/
	int main()
	{
		MEMEGOD_HERE;
		ll n,m,x,y,ans=1;
		cin>>n>>m;

		if(n=1)
		{
			cout<<"1\n";
			return 0;
		}
		ll h[n]={0};
		while(m--)
		{
			cin>>x>>y;
			x--;
			y--;
			h[x]++;
			h[y]++;
		}

		ll co=0;
		for(i=0;i<n;i++)
			if(h[i])
				co+=1;

		cout<<pow(2,co-1)<<"\n";
		return 0;
	}


#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define MEMEGOD_HERE ios_base::sync_with_stdio(0),cin.tie(0);cout.tie(0);
#define cnt1br __built_popcountll();

using namespace std;

//std::setprecision(5)

	int main()
	{
		MEMEGOD_HERE;
		ll n,m,x,y,co;
		cin>>n>>m;

		set <ll> s;
		while(m--)
		{
			cin>>x>>y;
			s.insert(x);
			s.insert(y);
		}

		co=s.size();
		if(co!=n)
			co--;
		x=(pow(2,co-1));
		cout<<max(1ll,x)<<"\n";
		return 0;
	}


#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define MEMEGOD_HERE ios_base::sync_with_stdio(0),cin.tie(0);cout.tie(0);
#define cnt1br __built_popcountll();

using namespace std;

//std::setprecision(5)

	int main()
	{
		MEMEGOD_HERE;
		ll n,m,x,y,ans=1;
		cin>>n>>m;

		ll h[n]={0};
		while(m--)
		{
			cin>>x>>y;
			x--;
			y--;
			h[x]++;
			h[y]++;
		}

		ll co=0;
		for(ll i=0;i<n;i++)
			if(h[i]>0)
				co+=1;

		cout<<max(1,pow(2,co-1))<<"\n";
		return 0;
	}


#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define MEMEGOD_HERE ios_base::sync_with_stdio(0),cin.tie(0);cout.tie(0);
#define cnt1br __built_popcountll();
using namespace std;

//std::setprecision(5)
	vector <ll> v(60,0);
	vector <ll> graph[60];

	void dfs(ll x)
	{
		if(!v[x])
		{
			v[x]=1;
			for(auto itr:graph[x])
				dfs(itr);
		}
	}

	int main()
	{
		MEMEGOD_HERE;

		ll t=1;
		//cin>>t;
		while(t--)
		{
			ll n,m,i,x,y;
			cin>>n>>m;
			while(m--)
			{
				cin>>x>>y;
				graph[x].pb(y);
				graph[y].pb(x);
			}
			ll co=0;
			for(i=1;i<=n;i++)
			{
				if(v[i]==0)
				{
					dfs(i);
					co++;
				}
			}
			ll ans=pow(2,n-co);
			cout<<ans<<"\n";
		}
		return 0;
	}


#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define MEMEGOD_HERE ios_base::sync_with_stdio(0),cin.tie(0);cout.tie(0);
#define cnt1br __built_popcountll();

using namespace std;

//std::setprecision(5)

	int main()
	{
		MEMEGOD_HERE;
		ll n,m,x,y,ans=1;
		cin>>n>>m;

		ll h[n]={0};
		while(m--)
		{
			cin>>x>>y;
			x--;
			y--;
			h[x]++;
			h[y]++;
		}

		ll co=0;
		for(ll i=0;i<n;i++)
			if(h[i]>0)
				co+=1;
		x=pow(2,co-1);
		if(co!=n)
			x/=2;
		cout<<max(1ll,x)<<"\n";
		return 0;
	}


#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define MEMEGOD_HERE ios_base::sync_with_stdio(0),cin.tie(0);cout.tie(0);
#define cnt1br __built_popcountll();

using namespace std;

//std::setprecision(5)

	int main()
	{
		MEMEGOD_HERE;
		ll n,m,x,y,ans=1;
		cin>>n>>m;

		if(n==1)
		{
			cout<<"1\n";
			return 0;
		}
		ll h[n]={0};
		while(m--)
		{
			cin>>x>>y;
			x--;
			y--;
			h[x]++;
			h[y]++;
		}

		ll co=0;
		for(ll i=0;i<n;i++)
			if(h[i]>0)
				co+=1;

		cout<<pow(2,co-1)<<"\n";
		return 0;
	}


#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define MEMEGOD_HERE ios_base::sync_with_stdio(0),cin.tie(0);cout.tie(0);
#define cnt1br __built_popcountll();

using namespace std;

//std::setprecision(5)

	int main()
	{
		MEMEGOD_HERE;
		ll n,m,x,y,ans=1;
		cin>>n>>m;

		ll h[n]={0};
		while(m--)
		{
			cin>>x>>y;
			x--;
			y--;
			h[x]++;
			h[y]++;
		}

		ll co=0;
		for(ll i=0;i<n;i++)
			if(h[i]>0)
				co+=1;
		x=pow(2,co-1);
		cout<<max(1ll,x)<<"\n";
		return 0;
	}


#include <bits/stdc++.h>
using namespace std;
int counter[100];
int number[10000];
int parent[100];
int sz[100];

int find(int p) {
    if(parent[p] == -1) return p;
    return (parent[p] = find(parent[p]));
}
void Union(int p, int q) {
    p = find(p);
    q = find(q);
    if(p == q) return;
    if(sz[p] > sz[q]) swap(p,q);
    parent[p] = q;
    sz[q] += sz[p];
}

int main() {
    int n, m,x,y;
    int tam=1;
    int max = 0;
    //memset(parent, -1 , sizeof(int)*100);
    //memset(sz, 1, sizeof(int)*100);
    for (int i = 0; i < 100; i++) parent[i] = -1, sz[i] = 1;

    cin >> n >> m;

    for (int i = 0; i < m; i++) {
        cin >> x >> y;
        int xpai, ypai;
        xpai = find(x);
        ypai = find(y);
        if(xpai != ypai) {
            Union(x,y);
        }
    }
    for (int i = 1; i <= n; i++) {
        if(parent[i] == -1 && sz[i] != 1) {
            max += sz[i];
        }
    }
    if(max > 0) max--;

    /*
    if(max >= 1) number[0] = 2;
    else number[0] = 1;

    for (int i = 0; i < max-1; i++) {

        for (int j = 0; j < tam; j++) {
            number[j] = number[j]*2;
        }
        for(int j = 0; j < tam; j++) {
            if(number[j] >= 10) {
                number[j] = number[j]%10;
                number[j+1]++;
                if(j+1+1 > tam) tam = j+1+1;
            }
        }

    }

    for (int i = tam-1; i >= 0; i--) {
        cout << number[i];
    }

    cout << endl;
    */
   cout<< pow(2, max) << endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
int counter[100];
int number[10000];
int parent[100];
int sz[100];

int find(int p) {
    if(parent[p] == -1) return p;
    return (parent[p] = find(parent[p]));
}
void Union(int p, int q) {
    p = find(p);
    q = find(q);
    if(p == q) return;
    if(sz[p] > sz[q]) swap(p,q);
    parent[p] = q;
    sz[q] += sz[p];
}

int main() {
    int n, m,x,y;
    int tam=1;
    int max = 0;
    //memset(parent, -1 , sizeof(int)*100);
    //memset(sz, 1, sizeof(int)*100);
    for (int i = 0; i < 100; i++) parent[i] = -1, sz[i] = 1;

    cin >> n >> m;

    for (int i = 0; i < m; i++) {
        cin >> x >> y;
        int xpai, ypai;
        xpai = find(x);
        ypai = find(y);
        if(xpai != ypai) {
            Union(x,y);
        }
    }
    for (int i = 1; i <= n; i++) {
        if(parent[i] == -1 && sz[i] != 1) {
            max += sz[i]-1;
        }
    }

    if(max >= 1) number[0] = 2;
    else number[0] = 1;

    for (int i = 0; i < max-1; i++) {

        for (int j = 0; j < tam; j++) {
            number[j] = number[j]*2;
        }
        for(int j = 0; j < tam; j++) {
            if(number[j] >= 10) {
                number[j] = number[j]%10;
                number[j+1]++;
                if(j+1+1 > tam) tam = j+1+1;
            }
        }

    }

    for (int i = tam-1; i >= 0; i--) {
        cout << number[i];
    }

    cout << endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
int counter[100];
int number[10000];
int parent[100];
int sz[100];

int find(int p) {
    if(parent[p] == -1) return p;
    return (parent[p] = find(parent[p]));
}
void Union(int p, int q) {
    p = find(p);
    q = find(q);
    if(p == q) return;
    if(sz[p] > sz[q]) swap(p,q);
    parent[p] = q;
    sz[q] += sz[p];
}

int main() {
    int n, m,x,y;
    int tam=1;
    int max = 0;
    //memset(parent, -1 , sizeof(int)*100);
    //memset(sz, 1, sizeof(int)*100);
    for (int i = 0; i < 100; i++) parent[i] = -1, sz[i] = 1;

    cin >> n >> m;

    for (int i = 0; i < m; i++) {
        cin >> x >> y;
        int xpai, ypai;
        xpai = find(x);
        ypai = find(y);
        if(xpai != ypai) {
            Union(x,y);
        }
    }
    for (int i = 1; i <= n; i++) {
        if(sz[i] > max) max = sz[i];
    }
    max--;

    /*
    if(max >= 1) number[0] = 2;
    else number[0] = 1;

    for (int i = 0; i < max-1; i++) {

        for (int j = 0; j < tam; j++) {
            number[j] = number[j]*2;
        }
        for(int j = 0; j < tam; j++) {
            if(number[j] >= 10) {
                number[j] = number[j]%10;
                number[j+1]++;
                if(j+1+1 > tam) tam = j+1+1;
            }
        }

    }

    for (int i = tam-1; i >= 0; i--) {
        cout << number[i];
    }

    cout << endl;
    */
   cout<< pow(2, max) << endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
int counter[100];
int number[10000];
int parent[100];
int sz[100];

int find(int p) {
    if(parent[p] == -1) return p;
    return (parent[p] = find(parent[p]));
}
void Union(int p, int q) {
    p = find(p);
    q = find(q);
    if(p == q) return;
    if(sz[p] > sz[q]) swap(p,q);
    parent[p] = q;
    sz[q] += sz[p];
}

int main() {
    int n, m,x,y;
    int tam=1;
    int max = 0;
    //memset(parent, -1 , sizeof(int)*100);
    //memset(sz, 1, sizeof(int)*100);
    for (int i = 0; i < 100; i++) parent[i] = -1, sz[i] = 1;

    cin >> n >> m;

    for (int i = 0; i < m; i++) {
        cin >> x >> y;
        int xpai, ypai;
        xpai = find(x);
        ypai = find(y);
        if(xpai != ypai) {
            Union(x,y);
        }
    }
    for (int i = 1; i <= n; i++) {
        if(parent[i] == -1 && sz[i] != 1) {
            max += sz[i]-1;
        }
    }

    /*
    if(max >= 1) number[0] = 2;
    else number[0] = 1;

    for (int i = 0; i < max-1; i++) {

        for (int j = 0; j < tam; j++) {
            number[j] = number[j]*2;
        }
        for(int j = 0; j < tam; j++) {
            if(number[j] >= 10) {
                number[j] = number[j]%10;
                number[j+1]++;
                if(j+1+1 > tam) tam = j+1+1;
            }
        }

    }

    for (int i = tam-1; i >= 0; i--) {
        cout << number[i];
    }

    cout << endl;
    */
   cout<< pow(2, max) << endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
int counter[100];
int number[10000];
int parent[100];
int sz[100];

int find(int p) {
    if(parent[p] == -1) return p;
    return (parent[p] = find(parent[p]));
}
void Union(int p, int q) {
    p = find(p);
    q = find(q);
    if(p == q) return;
    if(sz[p] > sz[q]) swap(p,q);
    parent[p] = q;
    sz[q] += sz[p];
}

int main() {
    int n, m,x,y;
    int tam=1;
    int max = 0;
    //memset(parent, -1 , sizeof(int)*100);
    //memset(sz, 1, sizeof(int)*100);
    for (int i = 0; i < 100; i++) parent[i] = -1, sz[i] = 1;

    cin >> n >> m;

    for (int i = 0; i < m; i++) {
        cin >> x >> y;
        int xpai, ypai;
        xpai = find(x);
        ypai = find(y);
        if(xpai != ypai) {
            Union(x,y);
        }
    }
    for (int i = 1; i <= n; i++) {
        if(parent[i] == -1 && sz[i] != 1) {
            max += sz[i];
        }
    }
    max--;

    /*
    if(max >= 1) number[0] = 2;
    else number[0] = 1;

    for (int i = 0; i < max-1; i++) {

        for (int j = 0; j < tam; j++) {
            number[j] = number[j]*2;
        }
        for(int j = 0; j < tam; j++) {
            if(number[j] >= 10) {
                number[j] = number[j]%10;
                number[j+1]++;
                if(j+1+1 > tam) tam = j+1+1;
            }
        }

    }

    for (int i = tam-1; i >= 0; i--) {
        cout << number[i];
    }

    cout << endl;
    */
   cout<< pow(2, max) << endl;

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define INF 1e7
#define st string
#define pb push_back
#define eb emplace_back
#define pii pair<int, int>
#define fopen freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
#define fastio ios_base::sync_with_stdio(false); cin.tie(NULL);
#define test(x) int t; cin >> t; while(t--) x();

//int dx[] = {0, 0, 1, -1};
//int dy[] = {1, -1, 0, 0};

vector<int>adj[100005];
queue<int>q;
bool vist[100005];
int n, m, a, b;

int dfs(int node){
    int res = 1;
    vist[node] = true;
    for(auto neigh : adj[node]){
        if(!vist[neigh]){
            res += dfs(neigh);
        }
    }
    return res;
}

void solve(){
    cin >> n >> m;
    for(int i = 0; i < m; i++) {
        cin >> a >> b;
        adj[a].pb(b);
        adj[b].pb(a);
    }
    int ans = 0;
    for(int i = 1; i <= n; i++){
        if(!vist[i]){
            //cout << "AQUI";
            ans += (dfs(i) - 1);
        }
    }
    cout << (ll) (1<<ans) << '\n';
}

int main(){
    fastio
    solve();
    return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define INF 1e7
#define st string
#define pb push_back
#define eb emplace_back
#define pii pair<int, int>
#define fopen freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
#define fastio ios_base::sync_with_stdio(false); cin.tie(NULL);
#define test(x) int t; cin >> t; while(t--) x();

//int dx[] = {0, 0, 1, -1};
//int dy[] = {1, -1, 0, 0};

vector<int>adj[100005];
queue<int>q;
bool vist[100005];
int n, m, a, b;

int bfs(int node){
    int res = 1;
    vist[node] = true;
    q.push(node);
    while(!q.empty()) {
        int x = q.front(); q.pop();
        for (auto neigh : adj[x]) {
            if (!vist[neigh]) {
                vist[neigh] = true;
                res++;
                q.push(neigh);
            }
        }
    }
    return res;
}

void solve(){
    cin >> n >> m;
    for(int i = 0; i < m; i++) {
        cin >> a >> b;
        adj[a].pb(b);
        adj[b].pb(a);
    }
    int ans = 0;
    for(int i = 1; i <= n; i++){
        if(!vist[i]){
            //cout << "AQUI";
            ans += (bfs(i) - 1);
        }
    }
    cout << (ll) pow(2, ans) << '\n';
}

int main(){
    fastio
    solve();
    return 0;
}


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

#define INF 1e7
#define st string
#define pb push_back
#define eb emplace_back
#define pii pair<int, int>
#define fopen freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
#define fastio ios_base::sync_with_stdio(false); cin.tie(NULL);
#define test(x) int t; cin >> t; while(t--) x();

//int dx[] = {0, 0, 1, -1};
//int dy[] = {1, -1, 0, 0};

vector<int>adj[100005];
queue<int>q;
bool vist[100005];
int n, m, a, b, mod = 1e9 + 7;

int dfs(int node){
    int res = 1;
    vist[node] = true;
    for(auto neigh : adj[node]){
        if(!vist[neigh]){
            res += dfs(neigh);
        }
    }
    return res;
}

void solve(){
    cin >> n >> m;
    for(int i = 0; i < m; i++) {
        cin >> a >> b;
        adj[a].pb(b);
        adj[b].pb(a);
    }
    int ans = 0;
    for(int i = 1; i <= n; i++){
        if(!vist[i]){
            //cout << "AQUI";
            ans += (dfs(i) - 1);
        }
    }
    cout << (ll) pow(2, ans) << '\n';
}

int main(){
    fastio
    solve();
    return 0;
}