#include <bits/stdc++.h>
#define TASK "aksdjkads"
#define INT_LIM (int) 2147483647
#define LL_LIM (long long) 9223372036854775807
#define endl '\n'
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define BIT(i,x) (((i)>>(x))&1)
#define FOR(i,a,b) for(int i = (a); i<=(b); i++)
#define FORD(i,a,b) for(int i = (a); i>=(b); i--)
#define ll long long
#define pii pair<int,int>
using namespace std;
///------------------------------------------///
const int MOD = 1e9+7;
class modInt{
private:
int val;
public:
modInt(): val(0) {};
modInt(long long _val): val(int(_val%MOD))
{
if (val<0) val+=MOD;
}
void operator += (const modInt &other)
{
val+=other.val;
if (val>=MOD) val-=MOD;
}
void operator -= (const modInt &other)
{
val-=other.val;
if (val<0) val+=MOD;
}
void operator *= (const modInt &other)
{
val = 1LL*val*other.val%MOD;
}
modInt operator + (const modInt &other)
{
modInt ret = *this;
ret+= other;
return ret;
}
modInt operator - (const modInt &other)
{
modInt ret = *this;
ret-= other;
return ret;
}
modInt operator * (const modInt &other)
{
modInt ret = *this;
ret*= other;
return ret;
}
modInt inverse(modInt x)
{
modInt ret = 1; int p = MOD-2;
while (p>0)
{
if (p&1) ret*=x;
x*=x; p>>=1;
}
return ret;
}
void operator /= (const modInt &other)
{
(*this)*= inverse(other);
}
modInt operator / (const modInt &other)
{
modInt ret = *this;
ret/=other;
return ret;
}
explicit operator int()
{
return val;
}
friend ostream & operator << (ostream &cout, const modInt &x)
{
cout << x.val;
return cout;
}
friend istream & operator >> (istream &cin, modInt &x)
{
ll tmp;
cin >> tmp;
x = modInt(tmp);
return cin;
}
};
modInt pw(modInt x, int p)
{
modInt ret = 1;
while (p>0)
{
if (p&1) ret*=x;
x*=x; p>>=1;
}
return ret;
}
int m,n;
modInt fact[3005], inv[3005];
void prep(int MAXN)
{
fact[0] = 1;
FOR(i, 1, MAXN) fact[i] = fact[i-1]*i;
inv[MAXN] = modInt(1)/fact[MAXN];
FORD(i, MAXN, 1)
{
inv[i-1] = inv[i]*i;
}
}
modInt nCk(int n, int k)
{
if (k<0 || k>n) return 0;
return int(fact[n]*inv[n-k]*inv[k]);
}
void inp()
{
prep(3000);
cin >> m >> n;
}
int f[3001][3001];
int calc(int x, int y)
{
if (x<1 || y<1) return 1;
if (f[x][y]!=-1) return f[x][y];
modInt ret = calc(x,y-1);
ret+= nCk(x,2)*calc(x-2,y-1);
return f[x][y] = (int)ret;
}
void solve()
{
memset(f, -1, sizeof(f));
modInt ans = 0;
FOR(k, 0, min(n,m))
{
modInt term = nCk(m,k)*nCk(n,k)*fact[k]*pw(4,k);
FOR(l, 0, min(m-k, (n-k)/2))
{
modInt term2 = nCk(m-k,l)*nCk(n-k,2*l)*fact[2*l]/pw(2,l);
ans+= term*term2*calc(m-k-l, n-k-2*l);
}
}
ans-=1;
cout << ans;
}
signed main()
{
///--------------------------///
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
if (fopen(TASK".INP","r")!=NULL)
{
freopen(TASK".INP","r",stdin);
freopen(TASK".OUT","w",stdout);
}
///--------------------------///
int NTEST = 1;
//cin >> NTEST;
while (NTEST--)
{
inp();
solve();
}
return 0;
}
///------------------------------------------///
Compilation message (stderr)
tents.cpp: In function 'int main()':
tents.cpp:171:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
171 | freopen(TASK".INP","r",stdin);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
tents.cpp:172:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
172 | freopen(TASK".OUT","w",stdout);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |