// #define DEBUGGING
#include <bits/stdc++.h>
#define endl '\n'
#define ALL(V) (V).begin(), (V).end()
#define ALLR(V) (V).rbegin(), (V).rend()
using ll = std::int64_t;
using ull = std::uint64_t;
using PLL = std::pair<ll, ll>;
using TLL = std::tuple<ll, ll, ll>;
template <typename T> using V = std::vector<T>;
template <typename T> using VV = V<V<T>>;
template <typename T> const T& var_min(const T &t) { return t; }
template <typename T> const T& var_max(const T &t) { return t; }
template <typename T, typename... Tail> const T& var_min(const T &t, const Tail&... tail) { return std::min(t, var_min(tail...)); }
template <typename T, typename... Tail> const T& var_max(const T &t, const Tail&... tail) { return std::max(t, var_max(tail...)); }
template <typename T, typename... Tail> void chmin(T &t, const Tail&... tail) { t = var_min(t, tail...); }
template <typename T, typename... Tail> void chmax(T &t, const Tail&... tail) { t = var_max(t, tail...); }
template <typename T> const T& clamp(const T &t, const T &low, const T &high) { return std::max(low, std::min(high, t)); }
template <typename T> void chclamp(T &t, const T &low, const T &high) { return t = clamp(t, low, high); }
namespace init__ { struct InitIO { InitIO() { std::cin.tie(nullptr); std::ios_base::sync_with_stdio(false); std::cout << std::fixed << std::setprecision(30); } } init_io; }
#define mv_rec make_v(init, tail...)
template <typename T> T make_v(T init) { return init; }
template <typename T, typename... Tail> auto make_v(T init, size_t s, Tail... tail) { return V<decltype(mv_rec)>(s, mv_rec); }
#undef mv_rec
using namespace std;

#ifdef DEBUGGING
#include "../../debug/debug.cpp"
#else
#define DEBUG(...) 0
#define DEBUG_SEPARATOR_LINE 0
#endif

class Dinic {
    struct Edge {
        ll to, cap, rev_idx;
    };
    
    VV<Edge> edges;
    const ll inf;

    V<ll> bfs(ll S) {
        V<ll> dist(edges.size(), -1);
        queue<PLL> que;
        que.emplace(S, 0);
        dist[S] = 0;
        while (que.size()) {
            ll now, d;
            tie(now, d) = que.front();
            que.pop();
            for (const auto &e : edges[now]) {
                if (e.cap <= 0) continue;
                ll nxt = e.to;
                if (dist[nxt] != -1 && dist[nxt] <= d + 1) continue;
                dist[nxt] = d + 1;
                que.emplace(nxt, d + 1);
            }
        }
        return move(dist);
    }

    ll dfs(ll now, ll pre, ll T, ll flow, const V<ll> &dist, V<ll> &watched) {
        if (now == T) return flow;
        for (ll i = watched[now] + 1; i < edges[now].size(); i++) {
            watched[now]++;
            auto &e = edges[now][i];
            if (dist[e.to] <= dist[now]) continue;
            if (e.cap <= 0) continue;
            if (e.to == pre) continue;
            ll f = dfs(e.to, now, T, min(flow, e.cap), dist, watched);
            e.cap -= f;
            edges[e.to][e.rev_idx].cap += f;
            if (f > 0) return f;
        }
        return 0;
    }

public: 
    Dinic(const VV<PLL> &v, ll inf) : inf(inf) {
        edges.resize(v.size());
        for (ll i = 0; i < v.size(); i++) {
            for (auto e : v[i]) {
                edges[i].push_back((Edge) {e.first, e.second, (ll)edges[e.first].size()} );
                edges[e.first].push_back((Edge) {i, 0, (ll)edges[i].size() - 1} );
            }
        }
    }

    Dinic(const VV<PLL> &v) : Dinic(v, 5e15) {};

    ll max_flow(ll S, ll T) {
        ll ret = 0;
        while (true) {
            auto dist = bfs(S);
            if (dist[T] == -1) break;
            V<ll> watched(edges.size(), -1);
            while (true) {
                ll tmp = dfs(S, -1, T, inf, dist, watched);
                if (tmp == 0) break;
                ret += tmp;
            }
        }
        return ret;
    }
};

ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }

bool solve() {
    ll M, N;
    cin >> M >> N;
    if (M == 0 && N == 0) return false;

    V<ll> B(M), R(N);
    for (ll &e : B) cin >> e;
    for (ll &e : R) cin >> e;

    ll start = M + N;
    ll goal = start + 1;
    VV<PLL> edges(goal + 1);
    for (ll i = 0; i < M; i++) for (ll j = 0; j < N; j++) {
        ll a = B[i], b = R[j];
        if (gcd(a, b) == 1) continue;
        edges[i].emplace_back(M + j, 1);
    }

    for (ll i = 0; i < M; i++) edges[start].emplace_back(i, 1);
    for (ll i = 0; i < N; i++) edges[M + i].emplace_back(goal, 1);

    Dinic dinic(edges);

    cout << dinic.max_flow(start, goal) << endl;
    return true;
}

int main() {
    while (solve());
    return 0;
}



Measured memory_bytes: 14244