#include <bits/stdc++.h>
// #include "push_relabel.h"

using namespace std;

typedef long long ll;
typedef pair<ll, ll> P;

#define each(i,a) for (auto&& i : a)
#define FOR(i,a,b) for (ll i=(a),__last_##i=(b);i<__last_##i;i++)
#define RFOR(i,a,b) for (ll i=(b)-1,__last_##i=(a);i>=__last_##i;i--)
#define REP(i,n) FOR(i,0,n)
#define RREP(i,n) RFOR(i,0,n)
#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME
#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)
#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)
#define pb push_back
#define eb emplace_back
#define all(a) (a).begin(),(a).end()
#define chmin(x,v) x = min(x, v)
#define chmax(x,v) x = max(x, v)

const ll linf = 1e18;
const double eps = 1e-12;
const double pi = acos(-1);

template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
  each(x,vec) is >> x;
  return is;
}
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& vec) {
  rep(i,vec.size()) {
    if (i) os << " ";
    os << vec[i];
  }
  return os;
}
template<typename T>
ostream& operator<<(ostream& os, const vector< vector<T> >& vec) {
  rep(i,vec.size()) {
    if (i) os << endl;
    os << vec[i];
  }
  return os;
}

class MaxFlow {
public:
  struct Edge {
    ll to, cap, dcap, rev;
    void update() {
      cap += dcap;
      dcap = 0;
    }
    ll capacity() const {
      return cap + dcap;
    }
  };
  vector<vector<Edge>> G;
private:
  bool is_debug;
  ll V;
  vector<ll> bfs(ll s) {
    vector<ll> dist(V, linf);
    dist[s] = 0;
    queue<ll> Q; Q.push(s);
    while ( !Q.empty() ) {
      ll v = Q.front(); Q.pop();
      each(e, G[v]) {
        if (e.cap > 0 && dist[e.to] == linf) {
          dist[e.to] = dist[v]+1;
          Q.push(e.to);
        }
      }
    }
    return dist;
  }
  vector<ll> rbfs(ll s) {
    vector<ll> dist(V, linf);
    dist[s] = 0;
    queue<ll> Q; Q.push(s);
    while ( !Q.empty() ) {
      ll v = Q.front(); Q.pop();
      each(e, G[v]) {
        if (rev(e).cap > 0 && dist[e.to] == linf) {
          dist[e.to] = dist[v]+1;
          Q.push(e.to);
        }
      }
    }
    return dist;
  }
public:
  const vector<vector<Edge>>& Graph() {
    return G;
  }
  MaxFlow(ll V, bool is_debug=false) : V(V), G(V), is_debug(is_debug) {}
  void init(ll n) {
    V = n;
    G.assign(V, vector<Edge>());
  }
  void add(ll from, ll to, ll cap) {
    if (is_debug) cout << "ADD: " << from << " " << to << " " << cap << endl;
    assert(V > 0);
    G[from].pb({to, cap, 0, (ll)G[to].size()});
    G[to].pb({from, 0, 0, (ll)G[from].size()-1});
  }
  // S -> s, T -> t に inf は自力で
  void add(ll from, ll to, ll min_flow, ll cap, ll S, ll T) {
    if (is_debug) cout << endl << "ADD_MIN:" << from << " " << to << " " << min_flow << " " << cap << endl;
    add(from, to, cap-min_flow);
    add(S, to, min_flow);
    add(from, T, cap);
    if (is_debug) cout << endl;
  }
  Edge& rev(const Edge& e) {
    return G[e.to][e.rev];
  }
  ll flow(ll s, ll t, ll f=linf) {
    ll res = 0;
    vector<ll> d;
    while (f > 0) {
      vector<ll> dist = bfs(s), rdist = rbfs(t);
      d.pb(*max_element(all(dist)));
      if (dist[t] == linf) break;
      vector<vector<ll>> dist_to_nodes(V+1);
      rep(i, V) {
        if (dist[i] < linf) {
          dist_to_nodes[dist[i]].pb(i);
        }
      }
      vector<ll> f(V, 0);
      f[s] = linf;
      rep(i, V+1) each(v, dist_to_nodes[i]) each(e, G[v]) {
        if (rdist[e.to] != rdist[v] - 1) continue;
        if (dist[e.to] != dist[v] + 1) continue;
        if (e.capacity() == 0) continue;
        ll use = min(e.capacity(), f[v]);
        f[v] -= use, f[e.to] += use;
        e.dcap -= use, rev(e).dcap += use;
      }
      // cout << "1: " << f << endl;
      // assert(f[t] > 0);
      if (f[t] == 0) break;
      res += f[t];
      f[t] = 0;
      rrep(i, 1, V+1) each(v, dist_to_nodes[i]) each(e, G[v]) {
        if (rdist[e.to] != rdist[v] + 1) continue;
        if (dist[e.to] != dist[v] - 1) continue;
        if (e.dcap <= 0) continue;
        ll use = min(e.dcap, f[v]);
        f[v] -= use, f[e.to] += use;
        e.dcap -= use, rev(e).dcap += use;
      }
      // cout << "2: " << f << endl;
      rep(v, V) if (v != s) assert(f[v] == 0);
      rep(v, V) each(e, G[v]) e.update();
    }
    return res;
  }
};

ll gcd(ll a, ll b) {
  return b == 0 ? a : gcd(b, a % b);
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  ll n, m;
  while (cin >> n >> m, n || m) {
    vector<ll> a(n), b(m); cin >> a >> b;
    ll s = n + m, t = s + 1;
    MaxFlow mf(t+1);
    rep(i, n) rep(j, m) {
      if (gcd(a[i], b[j]) > 1) {
        mf.add(i, n+j, 1);
      }
    }
    rep(i, n) mf.add(s, i, 1);
    rep(i, m) mf.add(n+i, t, 1);
    cout << mf.flow(s, t) << endl;
  }
}



Measured memory_bytes: 13668