#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef long double ld;
typedef vector<ll> vl;
typedef vector<bool> vb;
typedef vector<string> vs;
typedef vector<char> vc;
typedef queue<ll> ql;
typedef deque<ll> dql;
typedef priority_queue<ll> pql;
typedef set<ll> sl;
typedef pair<ll, ll> pl;
typedef map<ll, ll> ml;
typedef vector<vl> vvl;
typedef vector<pl> vpl;
#define rep(i, n) for(ll i = 0; i < ll(n); i++)
#define rep2(i, k, n) for(ll i = ll(k); i <= ll(n); i++)
#define rep3(i, n, k) for(ll i = ll(n); i >= ll(k); i--)
#define all(v) (v).begin(), (v).end()
ll mod(ll a, ll b) {return (a % b + b) % b;}
ll quo(ll a, ll b) {return (a - mod(a, b)) / b;}
template <typename T, typename U> bool chmin(T &a, const U b) {if(a > b) {a = b; return 1;} return 0;}
template <typename T, typename U> bool chmax(T &a, const U b) {if(a < b) {a = b; return 1;} return 0;}
const ll INF = 1LL << 60;
const ll MOD = 3;
//const ll MOD = 998244353;
const ll MAX = 2e5;
const ld eps = 1e-9;
const char newl = '\n';

struct mint{
  ll val;
  mint() {}
  mint(ll x) {val = mod(x, MOD);}
  mint operator-() {return mint(-this->val);}
  bool operator==(mint a) {return this->val == a.val;}
  bool operator<(mint a) {return this->val < a.val;}
  bool operator!=(mint a) {return this->val != a.val;}
  mint operator+(mint a) {return mint(this->val + a.val);}
  mint operator-(mint a) {return mint(this->val - a.val);}
  mint operator*(mint a) {return mint(this->val * a.val);}
  mint operator/(mint a) {return mint(this->val * a.inv().val);}
  mint &operator+=(mint a) {return *this = *this + a;}
  mint &operator-=(mint a) {return *this = *this - a;}
  mint &operator*=(mint a) {return *this = *this * a;}
  mint &operator/=(mint a) {return *this = *this / a;}
  friend istream &operator>>(istream &is, mint &m) {
    is >> m.val;
    return is;
  }
  friend ostream &operator<<(ostream &os, mint &m) {
    os << m.val;
    return os;
  }
  mint pow(ll n) {
    if(n == 0) return 1;
    if(n & 1) return pow(n-1) * *this;
    mint ret = pow(n/2);
    return ret * ret;
  }
  vector<mint> powv(ll n) {
    vector<mint> vec(n+1, 1);
    rep2(i, 1, n) vec[i] = vec[i-1] * *this;
    return vec;
  }
  mint inv() {return pow(MOD-2);}
  vector<mint> invv(ll n) {
    vector<mint> vec(n+1, 1);
    rep2(i, 2, n) vec[i] = -vec[MOD%i] * (MOD/i);
    return vec;
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  ll n, m, ans = 1;
  cin >> n >> m;
  vl a(m), b(m);
  vb used(n, 0);
  vvl G(n);
  rep(i, m) {
    cin >> a[i] >> b[i];
    a[i]--, b[i]--;
    G[a[i]].push_back(b[i]);
    G[b[i]].push_back(a[i]);
  }
  vl parent(n, -1), root(n, -1);
  rep(i, n) {
    if(used[i]) continue;
    used[i] = 1;
    ql q;
    q.push(i);
    vl vec;
    while(!q.empty()) {
      ll v = q.front();
      q.pop();
      root[v] = i;
      for(ll u: G[v]) {
        if(used[u]) continue;
        used[u] = 1;
        q.push(u);
        vec.push_back(u);
        parent[u] = v;
      }
    }
    ll vs = vec.size(), tmp = 0;
    if(vs == 0) {ans *= 3; continue;}
    rep(bit, 1 << vs) {
      vector<mint> c(n, 0);
      c[vec[0]] = (bit & 1) + 1;
      rep2(j, 1, vs-1) c[vec[j]] = c[parent[vec[j]]] + ((bit >> j) & 1) + 1;
      bool ok = 1;
      rep(j, m) if(root[a[j]] == i && c[a[j]] == c[b[j]]) ok = 0;
      if(ok) tmp++;
    }
    ans *= tmp*3;
  }
  cout << ans << newl;
  return 0;
}
#include <bits/stdc++.h>
using namespace std;

int main() {
	int n, cnt1, cnt2, m;
	cin >> n >> m;
	cnt1 = cnt2 = 0;
	for (int i = 1; i <= n; i++) {
		string s;
		cin >> s;
		int cnt = 0;
		for (auto p : s) p == '1' ? cnt++ : 0;
		cnt & 1 ? cnt1++ : cnt2++;
	}
	cout << 1ll * cnt1 * cnt2 << endl;
}