#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
template <unsigned M_> struct ModInt {
static constexpr unsigned M = M_;
unsigned x;
constexpr ModInt() : x(0) {}
constexpr ModInt(unsigned x_) : x(x_ % M) {}
constexpr ModInt(unsigned long long x_) : x(x_ % M) {}
constexpr ModInt(int x_) : x(((x_ %= static_cast<int>(M)) < 0) ? (x_ + static_cast<int>(M)) : x_) {}
constexpr ModInt(long long x_) : x(((x_ %= static_cast<long long>(M)) < 0) ? (x_ + static_cast<long long>(M)) : x_) {}
ModInt &operator+=(const ModInt &a) { x = ((x += a.x) >= M) ? (x - M) : x; return *this; }
ModInt &operator-=(const ModInt &a) { x = ((x -= a.x) >= M) ? (x + M) : x; return *this; }
ModInt &operator*=(const ModInt &a) { x = (static_cast<unsigned long long>(x) * a.x) % M; return *this; }
ModInt &operator/=(const ModInt &a) { return (*this *= a.inv()); }
ModInt pow(long long e) const {
if (e < 0) return inv().pow(-e);
ModInt a = *this, b = 1; for (; e; e >>= 1) { if (e & 1) b *= a; a *= a; } return b;
}
ModInt inv() const {
unsigned a = M, b = x; int y = 0, z = 1;
for (; b; ) { const unsigned q = a / b; const unsigned c = a - q * b; a = b; b = c; const int w = y - static_cast<int>(q) * z; y = z; z = w; }
assert(a == 1); return ModInt(y);
}
ModInt operator+() const { return *this; }
ModInt operator-() const { ModInt a; a.x = x ? (M - x) : 0; return a; }
ModInt operator+(const ModInt &a) const { return (ModInt(*this) += a); }
ModInt operator-(const ModInt &a) const { return (ModInt(*this) -= a); }
ModInt operator*(const ModInt &a) const { return (ModInt(*this) *= a); }
ModInt operator/(const ModInt &a) const { return (ModInt(*this) /= a); }
template <class T> friend ModInt operator+(T a, const ModInt &b) { return (ModInt(a) += b); }
template <class T> friend ModInt operator-(T a, const ModInt &b) { return (ModInt(a) -= b); }
template <class T> friend ModInt operator*(T a, const ModInt &b) { return (ModInt(a) *= b); }
template <class T> friend ModInt operator/(T a, const ModInt &b) { return (ModInt(a) /= b); }
explicit operator bool() const { return x; }
bool operator==(const ModInt &a) const { return (x == a.x); }
bool operator!=(const ModInt &a) const { return (x != a.x); }
friend std::ostream &operator<<(std::ostream &os, const ModInt &a) { return os << a.x; }
};
constexpr unsigned MO = 1000000007;
using Mint = ModInt<MO>;
constexpr int LIM = 110;
Mint inv[LIM], fac[LIM], invFac[LIM];
void prepare() {
inv[1] = 1;
for (int i = 2; i < LIM; ++i) {
inv[i] = -((Mint::M / i) * inv[Mint::M % i]);
}
fac[0] = invFac[0] = 1;
for (int i = 1; i < LIM; ++i) {
fac[i] = fac[i - 1] * i;
invFac[i] = invFac[i - 1] * inv[i];
}
}
Mint binom(Int n, Int k) {
if (0 <= k && k <= n) {
assert(n < LIM);
return fac[n] * invFac[k] * invFac[n - k];
} else {
return 0;
}
}
template <class T> vector<vector<T>> zeta(const vector<T> &as) {
const int n = __lg(as.size());
assert(static_cast<int>(as.size()) == 1 << n);
vector<vector<T>> zas(1 << n, vector<T>(n + 1, 0));
for (int h = 0; h < 1 << n; ++h) zas[h][__builtin_popcount(h)] = as[h];
for (int i = 0; i < n; ++i) for (int h = 0; h < 1 << n; ++h) {
if (!(h & 1 << i)) {
for (int k = 0; k <= n; ++k) zas[h | 1 << i][k] += zas[h][k];
}
}
return zas;
}
template <class T> vector<T> moebius(vector<vector<T>> zas) {
const int n = zas[0].size() - 1;
assert(static_cast<int>(zas.size()) == 1 << n);
for (int i = 0; i < n; ++i) for (int h = 0; h < 1 << n; ++h) {
if (!(h & 1 << i)) {
for (int k = 0; k <= n; ++k) zas[h | 1 << i][k] -= zas[h][k];
}
}
vector<T> as(1 << n);
for (int h = 0; h < 1 << n; ++h) as[h] = zas[h][__builtin_popcount(h)];
return as;
}
vector<Mint> mul(const vector<Mint> &as, const vector<Mint> &bs) {
const int n = as.size() - 1;
vector<Mint> cs(n + 1, 0);
for (int i = 0; i <= n; ++i) for (int j = 0; i + j <= n; ++j) {
cs[i + j] += as[i] * bs[j];
}
return cs;
}
vector<Mint> power(const vector<Mint> &as, Mint e) {
/*
b = a^e
b' / b = e a' / a
a b' = e a' b
*/
const int n = as.size() - 1;
assert(as[0].x == 1);
vector<Mint> bs(n + 1, 0);
bs[0] = 1;
for (int i = 1; i <= n; ++i) {
Mint sum = 0;
for (int j = 1; j <= i; ++j) sum += ((e + 1) * j - i) * as[j] * bs[i - j];
bs[i] = inv[i] * sum;
}
return bs;
}
int uf[LIM];
int root(int u) {
return (uf[u] < 0) ? u : (uf[u] = root(uf[u]));
}
bool connect(int u, int v) {
u = root(u);
v = root(v);
if (u == v) return false;
if (uf[u] > uf[v]) swap(u, v);
uf[u] += uf[v];
uf[v] = u;
return true;
}
struct UnluckyNumber {
int numberOfColourings(int n, int m, int k, int z, vector <int> x, vector <int> y) {
prepare();
for (int i = 0; i < m; ++i) {
--x[i];
--y[i];
}
const Int numSelfs = (z % 2 == 0) ? 1 : 0;
const Int numPairs = ((min(z - 2, 2 * k - z) + 1) - numSelfs) / 2;
const Int numOthers = k - 2 * numPairs - numSelfs;
// two colors which cannot be adjacent
vector<Mint> fs(1 << n, 0);
for (int p = 0; p < 1 << n; ++p) {
fill(uf, uf + n, -1);
for (int i = 0; i < m; ++i) {
if ((p & 1 << x[i]) && (p & 1 << y[i])) {
connect(x[i], y[i]);
}
}
fs[p] = 1;
for (int u = 0; u < n; ++u) {
if (p & 1 << u) {
if (uf[u] < 0) {
fs[p] *= 2;
}
}
}
}
// independent set
vector<Mint> gs(1 << n, 0);
for (int p = 0; p < 1 << n; ++p) {
bool ok = true;
for (int i = 0; i < m; ++i) {
ok = ok && !((p & 1 << x[i]) && (p & 1 << y[i]));
}
if (ok) {
gs[p] += 1;
}
}
// any
vector<Mint> hs(1 << n, 1);
// f^numPairs g^numSelfs h^numOthers
auto zfs = zeta(fs);
auto zgs = zeta(gs);
auto zhs = zeta(hs);
for (int p = 0; p < 1 << n; ++p) {
zfs[p] = mul(mul(power(zfs[p], numPairs), power(zgs[p], numSelfs)), power(zhs[p], numOthers));
}
const auto res = moebius(zfs);
const Mint ans = res[(1 << n) - 1];
return ans.x;
}
};
int brute(int n, int m, int k, int z, vector <int> x, vector <int> y) {
int ans = 0;
for (int p = 0; p < 1 << (3 * n); ++p) {
vector<int> col(n);
for (int u = 0; u < n; ++u) {
col[u] = ((p >> (3 * u)) & 7) + 1;
}
bool ok = true;
for (int u = 0; u < n; ++u) {
ok = ok && (1 <= col[u] && col[u] <= k);
}
for (int i = 0; i < m; ++i) {
ok = ok && (col[x[i] - 1] + col[y[i] - 1] != z);
}
if (ok) {
++ans;
}
}
return ans;
}
int main() {
cout << UnluckyNumber().numberOfColourings(3, 3, 4, 4, {1, 2, 3}, {2, 3, 1}) << endl;
cout << UnluckyNumber().numberOfColourings(18, 18, 987654321, 1000000000, {1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 16, 17}, {2, 3, 1, 5, 6, 7, 4, 9, 10, 11, 12, 10, 11, 12, 11, 12, 17, 18}) << endl;
/*
for (int n = 2; n <= 5; ++n) {
for (int k = 1; k <= 8; ++k) {
for (int z = 2; z <= 2 * k; ++z) {
cerr << "n = " << n << ", k = " << k << ", z = " << z << " ..." << endl;
for (int p = 0; p < 1 << (n * (n - 1) / 2); ++p) {
vector<int> x, y;
int pos = 0;
for (int u = 0; u < n; ++u) for (int v = u + 1; v < n; ++v) {
if (p & 1 << pos) {
x.push_back(u + 1);
y.push_back(v + 1);
}
++pos;
}
int m = x.size();
const int brt = brute(n, m, k, z, x, y);
const int res = UnluckyNumber().numberOfColourings(n, m, k, z, x, y);
if (brt != res) {
cerr << "n = " << n << ", m = " << m << ", k = " << k << ", z = " << z << endl;
cerr << "x = "; pv(x.begin(), x.end());
cerr << "y = "; pv(y.begin(), y.end());
cerr << "brt = " << brt << endl;
cerr << "res = " << res << endl;
assert(false);
}
}
}
}
}
*/
return 0;
}