#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int n, m;
const int MOD = 1e9 + 7;
// Generate all valid states for a column
vector<int> generateValidStates(int n) {
vector<int> states;
int maxState = 1 << n;
for (int state = 0; state < maxState; ++state) {
// Check for vertical adjacency constraint (no two adjacent 1s)
if ((state & (state << 1)) == 0) {
states.push_back(state);
}
}
return states;
}
// Precompute transitions between states
unordered_map<int, vector<int>> generateTransitions(const vector<int>& states) {
unordered_map<int, vector<int>> transitions;
for (int s : states) {
for (int s_next : states) {
// Check for horizontal adjacency constraint (no overlapping 1s)
if ((s & s_next) == 0) {
transitions[s].push_back(s_next);
}
}
}
return transitions;
}
int main() {
cin >> n >> m;
vector<int> states = generateValidStates(n);
unordered_map<int, vector<int>> transitions = generateTransitions(states);
cout << transitions.size() << endl;
// Initialize DP table
unordered_map<int, int> dp_current, dp_next;
for (int state : states) {
dp_current[state] = 1; // Base case: one way to reach each state in the first column
}
// DP over columns
for (int col = 1; col < m; ++col) {
dp_next.clear();
for (auto& kv : dp_current) {
int s = kv.first;
int count = kv.second;
for (int s_next : transitions[s]) {
dp_next[s_next] = (dp_next[s_next] + count) % MOD;
}
}
dp_current.swap(dp_next); // Move to the next column
}
// Compute final answer
int answer = 0;
for (const auto& kv : dp_current) {
answer = (answer + kv.second) % MOD;
}
cout << answer << endl;
return 0;
}