Problem:
Score : 900 points

Problem Statement

Joisino has a lot of red and blue bricks and a large box.
She will build a tower of these bricks in the following manner.

First, she will pick a total of N bricks and put them into the box.
Here, there may be any number of bricks of each color in the box, as long as there are N bricks in total.
Particularly, there may be zero red bricks or zero blue bricks.
Then, she will repeat an operation M times, which consists of the following three steps:

Take out an arbitrary brick from the box.

Put one red brick and one blue brick into the box.

Take out another arbitrary brick from the box.

After the M operations, Joisino will build a tower by stacking the 2 \times M bricks removed from the box, in the order they are taken out.
She is interested in the following question: how many different sequences of colors of these 2 \times M bricks are possible?
Write a program to find the answer.
Since it can be extremely large, print the count modulo 10^9+7.

Constraints

1 \leq N \leq 3000

1 \leq M \leq 3000

Input

Input is given from Standard Input in the following format:

N M

Output

Print the count of the different possible sequences of colors of 2 \times M bricks that will be stacked, modulo 10^9+7.

Sample Input 1

2 3

Sample Output 1

56

A total of six bricks will be removed from the box. The only impossible sequences of colors of these bricks are the ones where the colors of the second, third, fourth and fifth bricks are all the same. Therefore, there are 2^6 - 2 \times 2 \times 2 = 56 possible sequences of colors.

Sample Input 2

1000 10

Sample Output 2

1048576

Sample Input 3

1000 3000

Sample Output 3

693347555

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<bitset>
#include<utility>
#include<functional>
#include<iomanip>
#include<sstream>
#include<ctime>
#include<cassert>
using namespace std;
#define y0 y0z
#define y1 y1z
#define yn ynz
#define j0 j0z
#define j1 j1z
#define jn jnz
#define tm tmz
#define buli(x) (__builtin_popcountll(x))
#define bur0(x) (__builtin_ctzll(x))
#define bul2(x) (63-__builtin_clzll(x))
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define fil(a,b) memset((a),(b),sizeof(a))
#define cl(a) fil(a,0)
#define siz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define rep(i,a,b) for (int i=(a),_ed=(b);i<_ed;i++)
#define per(i,a,b) for (int i=(b)-1,_ed=(a);i>=_ed;i--)
#define forg(i,gu) for (int i=gu;~i;i=e[i].next)
#define pw(x) ((ll(1))<<(x))
#define upmo(a,b) (((a)=((a)+(b))%mo)<0?(a)+=mo:(a))
#define mmo(a,b) (((a)=1ll*(a)*(b)%mo)<0?(a)+=mo:(a))
void getre(){int x=0;printf("%d\n",1/x);}
void gettle(){int res=1;while(1)res<<=1;printf("%d\n",res);}
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pii> vpii;
template<typename T,typename S>inline bool upmin(T&a,const S&b){return a>b?a=b,1:0;}
template<typename T,typename S>inline bool upmax(T&a,const S&b){return a<b?a=b,1:0;}
template<typename N,typename PN>inline N flo(N a,PN b){return a>=0?a/b:-((-a-1)/b)-1;}
template<typename N,typename PN>inline N cei(N a,PN b){return a>0?(a-1)/b+1:-(-a/b);}
template<typename N>N gcd(N a,N b){return b?gcd(b,a%b):a;}
template<typename N>inline int sgn(N a){return a>0?1:(a<0?-1:0);}
#if ( ( _WIN32 || __WIN32__ ) && __cplusplus < 201103L)
#define lld "%I64d"
#else
#define lld "%lld"
#endif
inline void gn(long long&x){
	int sg=1;char c;while(((c=getchar())<'0'||c>'9')&&c!='-');c=='-'?(sg=-1,x=0):(x=c-'0');
	while((c=getchar())>='0'&&c<='9')x=x*10+c-'0';x*=sg;
}
inline void gn(int&x){long long t;gn(t);x=t;}
inline void gn(unsigned long long&x){long long t;gn(t);x=t;}
inline void gn(double&x){double t;scanf("%lf",&t);x=t;}
inline void gn(long double&x){double t;scanf("%lf",&t);x=t;}
inline void gs(char *s){scanf("%s",s);}
inline void gc(char &c){while((c=getchar())>126 || c<33);}
inline void pc(char c){putchar(c);}
#ifdef JCVB
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif
typedef long long ll;
typedef double db;
inline ll sqr(ll a){return a*a;}
inline db sqrf(db a){return a*a;}
const int inf=0x3f3f3f3f;
//const ll inf=0x3f3f3f3f3f3f3f3fll;
const db pi=3.14159265358979323846264338327950288L;
const db eps=1e-6;
const int mo=1e9+7;
int qp(int a,ll b){int n=1;do{if(b&1)n=1ll*n*a%mo;a=1ll*a*a%mo;}while(b>>=1);return n;}


int n,m;
int b;

int f[3333][3333];
int totf[3333];
int g[3333][3333];
int totg[3333];
int main()
{
#ifdef JCVB
	//freopen("1.in","r",stdin);
	//freopen("1.out","w",stdout);
	int _time_jc=clock();
#endif
	gn(n);gn(m);
	b=n-1;
	int ret=qp(2,m+1);// no updown
	if(b==0){
		printf("%d\n",ret);
		return 0;
	}

	int ans=0;
	f[0][0]=1;
	rep(j,0,m+1)
		rep(k,0,j+1)if(f[j][k]){
			upmo(totf[j],f[j][k]);
			upmo(f[j+1][k],2ll*f[j][k]);
			if(k+1<=b)upmo(f[j+1][k+1],f[j][k]);
			if(k) upmo(f[j+1][k-1],f[j][k]);
		}
	g[0][0]=1;
	rep(j,0,m+1)
		rep(k,0,j+1)if(g[j][k]){
			upmo(totg[j],g[j][k]);
			upmo(g[j+1][k],2ll*g[j][k]);
			if(k+1<=b-1)upmo(g[j+1][k+1],g[j][k]);
			if(k) upmo(g[j+1][k-1],g[j][k]);
		}

	int tot=qp(4,m-1);
	int tmp=0;
	for (int l=2;l<=m-1;l++){
		for (int t=0;t+l<=m-1;t++){
			int re=m-1-t-l;
			re=qp(4,re);
			mmo(re,totf[t]);
			mmo(re,g[l-2][b-1]);
			upmo(tmp,re);
		}
	}
	mmo(tmp,2ll);
	upmo(tot,-tmp);
	mmo(tot,4);
	printf("%d\n",tot);
#ifdef JCVB
	debug("time: %d\n",int(clock()-_time_jc));
#endif
	return 0;
}