#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i, a, b) for(int i = (a); i < (b); ++i)
#define per(i, a, b) for(int i = (b) - 1; i >= (a); --i)
#define sz(a) (int)a.size()
#define de(a) cout << #a << " = " << a << endl
#define dd(a) cout << #a << " = " << a << " "
#define all(a) a.begin(), a.end()
#define pw(a) (1ll<<(x))
#define endl "\n"
typedef long long ll;
typedef double db;
typedef pair<int, int> pii;
typedef vector<int> vi;
//----
const int mod = 1e9 + 7, N = 1e6 + 5;
int c[5];
int dp[N] = {1, 1, 2};
int add(int a, int b) {
	int res = a + b;
	if(res >= mod)res -= mod;
	return res;
}
int mul(int a, int b) {
	return a * b % mod;
}
int main() {
	int n; cin >> n;
	rep(i, 0, n) {
		int x; cin >> x; c[x]++;
	}
	dp[1] = 1;
	rep(i, 3, c[1] + 1)dp[i] = add(dp[i - 1], mul((i - 1), dp[i - 2]));
	rep(i, n - c[2] + 1, n + 1)dp[c[1]] = mul(dp[c[1]], i);
	cout << dp[c[1]] << endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <ctype.h>
#include <deque>
#include <cstring>
#include <set>
#include <bitset>
#include <map>
#include <chrono>
#include <random>
#include <unordered_map>
#include <stdio.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef std::vector<int> vi;
typedef std::vector<bool> vb;
typedef std::vector<string> vs;
typedef std::vector<double> vd;
typedef std::vector<long long> vll;
typedef std::vector<std::vector<int> > vvi;
typedef vector<vll> vvll;
typedef std::vector<std::pair<int, int> > vpi;
typedef vector<vpi> vvpi;
typedef std::pair<int, int> pi;
typedef std::pair<ll, ll> pll;
typedef std::vector<pll> vpll;

const long long mod = 1000000007;
const unsigned gen_seed = std::chrono::system_clock::now().time_since_epoch().count();
std::mt19937_64 gen(gen_seed);

#define all(c) (c).begin(),(c).end()
#define forn(i, a, b) for(int i = a; i < b; i++)
#define read(x) scanf("%d", &x)
#define readv(x, n) vi x(n); forn(i,0,n) scanf("%d", &a[i])

#define pb push_back
#define mp make_pair
const int A = 500;
ll d[A+1][A+1];
ll fac[A+1];
ll ifac[A+1];
ll cfac[A+1][A+1];
ll cfac2[A+1][A+1];

ll gcd (ll a, ll b, ll & x, ll & y) {
    if (a == 0) {
        x = 0; y = 1;
        return b;
    }
    ll x1, y1;
    ll d = gcd (b%a, a, x1, y1);
    x = y1 - (b / a) * x1;
    y = x1;
    return d;
}

ll invmod(ll a, ll modulo) {
    ll x, y;
    gcd(a, modulo, x, y);
    return (x%modulo+modulo)%modulo;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.txt", "rt", stdin);
    freopen("output.txt", "wt", stdout);
#endif
    fac[0] = 1;
    for(ll i = 1; i<=A; i++) fac[i] = (fac[i-1]*i)%mod;
    forn(i,0,A+1) ifac[i] = invmod(fac[i], mod);
    d[0][0] = 1;
    forn(i,0,A+1) forn(j,0,i+1) cfac[i][j] = fac[i]*ifac[i-j]%mod;
    forn(i,0,A+1) forn(j,0,i+1) cfac2[i][j] = cfac[i][j]*(j+1)%mod;
    forn(b,0,A+1) forn(a,0,A+1) {
        if(a == 0) {
            if(b>0) d[0][b] = (d[0][b-1]*b)%mod;
            continue;
        }
        forn(tb,0,b+1) {
            d[a][b] += d[a-1][b-tb]*cfac[b][tb]%mod;
        }
        if(a>1) {
            ll cand = 0;
            forn(tb,0,b+1) {
                cand += d[a-2][b-tb]*cfac2[b][tb]%mod;
            }
            d[a][b] += cand*(a-1);
        }
        d[a][b] %= mod;

    }
    int n;
    scanf("%d", &n);
    int a= 0;
    int b = 0;
    forn(i,0,n) {
        int x;
        read(x);
        if(x==1) a++;
        else b++;
    }
    cout<<d[a][b];

}


#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long ll;

const int Maxn = 1000005;
const int mod = 1000000007;

int n;
int a, b;
int one[Maxn];

int main()
{
	scanf("%d", &n);
	while (n--) {
		int num; scanf("%d", &num);
		if (num == 1) a++;
		else if (num == 2) b++;
	}
	one[0] = 1; one[1] = 1;
	for (int i = 2; i <= a; i++)
		one[i] = (one[i - 1] + ll(i - 1) * one[i - 2]) % mod;
	int res = one[a];
	for (int i = 1; i <= b; i++)
		res = ll(res) * (a + i) % mod;
	printf("%d\n", res);
	return 0;
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Locale;
import java.util.StringTokenizer;

import static java.util.Arrays.deepToString;
import static java.util.Arrays.fill;

public class D {

	final static int MOD = 1000000007;
	static int[] fact;
	static int[][] d, special;

	static int get(int ones, int twos) {
		if (d[ones][twos] != -1) {
			return d[ones][twos];
		}
		if (ones + twos == 1) {
			return 1;
		}
		if (ones == 0) {
			return fact[twos];
		}
		long ans = get(ones - 1, twos);
		if (ones >= 2) {
			ans += (ones - 1) * get(ones - 2, twos);
		}
		if (twos >= 1) {
			ans += (twos) * get(ones, twos - 1);
		}
		if (ones >= 2 && twos >= 1) {
			long typeSum = 0;
			for (int len = 1; len <= twos; len++) {
				typeSum += (long) special[twos][len] * get(ones - 2, twos - len);
				typeSum %= MOD;
			}
			ans += (long) (ones - 1) * typeSum;
		}
		return d[ones][twos] = (int) (ans % MOD);
	}

	// static long special(int k, int len) {
	// long res = 1;
	// for (int t = k; t >= k - len + 1; t--) {
	// res *= t;
	// res %= MOD;
	// }
	// return res;
	// }

	static void solve() {
		int n = nextInt();
		int ones = 0, twos = 0;
		for (int i = 0; i < n; i++) {
			int k = nextInt();
			if (k == 1)
				ones++;
			else
				twos++;
		}
		// n = 500;
		// ones = 0;
		// twos = 500;
		d = new int[ones + 1][twos + 1];
		for (int[] dd : d) {
			fill(dd, -1);
		}
		fact = new int[n + 1];
		fact[0] = 1;
		for (int i = 1; i < fact.length; i++) {
			fact[i] = (int) (((long) fact[i - 1] * i) % MOD);
		}
		special = new int[n + 1][n + 1];
		for (int t = 1; t <= n; t++) {
			special[t][0] = 1;
			for (int len = 1; len <= t; len++) {
				special[t][len] = (int) ((long) special[t][len - 1] * (t - len + 1) % MOD);
			}
		}

		writer.println(get(ones, twos));
	}

	public static void main(String[] args) throws Exception {
		reader = new BufferedReader(new InputStreamReader(System.in));
		writer = new PrintWriter(System.out);
		Locale.setDefault(Locale.US);

		setTime();
		solve();
		printTime();
		printMemory();

		writer.close();
	}

	static BufferedReader reader;
	static PrintWriter writer;
	static StringTokenizer tok = new StringTokenizer("");
	static long systemTime;

	static void debug(Object... o) {
		System.err.println(deepToString(o));
	}

	static void setTime() {
		systemTime = System.currentTimeMillis();
	}

	static void printTime() {
		System.err.println("Time consumed: " + (System.currentTimeMillis() - systemTime));
	}

	static void printMemory() {
		System.err.println("Memory consumed: "
				+ (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1000 + "kb");
	}

	static String next() {
		while (!tok.hasMoreTokens()) {
			String w = null;
			try {
				w = reader.readLine();
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (w == null)
				return null;
			tok = new StringTokenizer(w);
		}
		return tok.nextToken();
	}

	static int nextInt() {
		return Integer.parseInt(next());
	}

	static long nextLong() {
		return Long.parseLong(next());
	}

	static double nextDouble() {
		return Double.parseDouble(next());
	}

	static BigInteger nextBigInteger() {
		return new BigInteger(next());
	}
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Locale;
import java.util.StringTokenizer;

import static java.util.Arrays.deepToString;
import static java.util.Arrays.fill;

public class D {

	final static int MOD = 1000000007;
	static int[] fact;
	static int[][] d, special;

	static int get(int ones, int twos) {
		if (d[ones][twos] != -1) {
			return d[ones][twos];
		}
		if (ones + twos == 1) {
			return 1;
		}
		if (ones == 0) {
			return fact[twos];
		}
		long ans = get(ones - 1, twos);
		if (ones >= 2) {
			ans += (long) (ones - 1) * get(ones - 2, twos);
		}
		if (twos >= 1) {
			ans += (long) (twos) * get(ones, twos - 1);
		}
		if (ones >= 2 && twos >= 1) {
			long typeSum = 0;
			for (int len = 1; len <= twos; len++) {
				typeSum += (long) special[twos][len] * get(ones - 2, twos - len);
				typeSum %= MOD;
			}
			ans += (long) (ones - 1) * typeSum;
		}
		return d[ones][twos] = (int) (ans % MOD);
	}

	// static long special(int k, int len) {
	// long res = 1;
	// for (int t = k; t >= k - len + 1; t--) {
	// res *= t;
	// res %= MOD;
	// }
	// return res;
	// }

	static void solve() {
		int n = nextInt();
		int ones = 0, twos = 0;
		for (int i = 0; i < n; i++) {
			int k = nextInt();
			if (k == 1)
				ones++;
			else
				twos++;
		}
		// n = 500;
		// ones = 250;
		// twos = 250;
		d = new int[ones + 1][twos + 1];
		for (int[] dd : d) {
			fill(dd, -1);
		}
		fact = new int[n + 1];
		fact[0] = 1;
		for (int i = 1; i < fact.length; i++) {
			fact[i] = (int) (((long) fact[i - 1] * i) % MOD);
		}
		special = new int[n + 1][n + 1];
		for (int t = 1; t <= n; t++) {
			special[t][0] = 1;
			for (int len = 1; len <= t; len++) {
				special[t][len] = (int) ((long) special[t][len - 1] * (t - len + 1) % MOD);
			}
		}

		writer.println(get(ones, twos));
	}

	public static void main(String[] args) throws Exception {
		reader = new BufferedReader(new InputStreamReader(System.in));
		writer = new PrintWriter(System.out);
		Locale.setDefault(Locale.US);

		setTime();
		solve();
		printTime();
		printMemory();

		writer.close();
	}

	static BufferedReader reader;
	static PrintWriter writer;
	static StringTokenizer tok = new StringTokenizer("");
	static long systemTime;

	static void debug(Object... o) {
		System.err.println(deepToString(o));
	}

	static void setTime() {
		systemTime = System.currentTimeMillis();
	}

	static void printTime() {
		System.err.println("Time consumed: " + (System.currentTimeMillis() - systemTime));
	}

	static void printMemory() {
		System.err.println("Memory consumed: "
				+ (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1000 + "kb");
	}

	static String next() {
		while (!tok.hasMoreTokens()) {
			String w = null;
			try {
				w = reader.readLine();
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (w == null)
				return null;
			tok = new StringTokenizer(w);
		}
		return tok.nextToken();
	}

	static int nextInt() {
		return Integer.parseInt(next());
	}

	static long nextLong() {
		return Long.parseLong(next());
	}

	static double nextDouble() {
		return Double.parseDouble(next());
	}

	static BigInteger nextBigInteger() {
		return new BigInteger(next());
	}
}


import java.io.*;
import java.util.*;

public class CF {
    FastScanner in;
    PrintWriter out;

    long mod = (long) 1e9 + 7;

    long getV(int n) {
        if (n <= 4) {
            return new long[]{ 1, 1, 2, 4, 10, 26, 76, 232 }[n];
        }
        long[] res = new long[n + 1];
        res[0] = res[1] = 1;
        for (int i = 2; i <= n; i++) {
            res[i] = (res[i - 1] + (i - 1) * res[i - 2]) % mod;
        }
        return res[n];
    }

    long getAns2(int x, int y) {
        long res = getV(x);
        for (int i = 0; i < y; i++) {
            res = (res * (x + i + 1)) % mod;
        }
        return res;
    }

    void solve() {
        int n = in.nextInt();
        int f = 0;
        for (int i = 0; i < n; i++) {
            if (in.nextInt() == 1) {
                f++;
            }
        }
        out.println(getAns2(f, n - f));

    }

    void run() {
        try {
            in = new FastScanner(new File("object.in"));
            out = new PrintWriter(new File("object.out"));

            solve();

            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    void runIO() {

        in = new FastScanner(System.in);
        out = new PrintWriter(System.out);

        solve();

        out.close();
    }

    class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(File f) {
            try {
                br = new BufferedReader(new FileReader(f));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        public FastScanner(InputStream f) {
            br = new BufferedReader(new InputStreamReader(f));
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return null;
                st = new StringTokenizer(s);
            }
            return st.nextToken();
        }

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }
    }

    public static void main(String[] args) {
        new CF().runIO();
    }
}


import java.io.*;
import java.util.*;

public class CF {
    FastScanner in;
    PrintWriter out;

    long mod = (long) 1e9 + 7;

    long getV(int n) {
        long[] res = new long[n + 1];
        res[0] = res[1] = 1;
        for (int i = 2; i <= n; i++) {
            res[i] = (res[i - 1] + (i - 1) * res[i - 2]) % mod;
        }
        return res[n];
    }

    long getAns2(int x, int y) {
        long res = getV(x);
        for (int i = 0; i < y; i++) {
            res = (res * (x + i + 1)) % mod;
        }
        return res;
    }

    void solve() {

        int n = in.nextInt();
        int f = 0;
        for (int i = 0; i < n; i++) {
            if (in.nextInt() == 1) {
                f++;
            }
        }
        out.println(getAns2(f, n - f));

    }

    void run() {
        try {
            in = new FastScanner(new File("object.in"));
            out = new PrintWriter(new File("object.out"));

            solve();

            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    void runIO() {

        in = new FastScanner(System.in);
        out = new PrintWriter(System.out);

        solve();

        out.close();
    }

    class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(File f) {
            try {
                br = new BufferedReader(new FileReader(f));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        public FastScanner(InputStream f) {
            br = new BufferedReader(new InputStreamReader(f));
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return null;
                st = new StringTokenizer(s);
            }
            return st.nextToken();
        }

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }
    }

    public static void main(String[] args) {
        new CF().runIO();
    }
}


import java.io.*;
import java.math.BigInteger;

public class Main
{
   public static void main(String[] args) throws IOException
   {
      new Main().run();
   }

   BufferedReader in;
   StreamTokenizer st;
   PrintWriter out;
   long modulo = 1000000007L;
   long[][] mas;
   long[] fact = new long[1000001];
   long[] factrev = new long[1000001];
   long[] p = new long[1000001];

   double nextDouble() throws IOException
   {
       st.nextToken();
       return (double)st.nval;
   }

   String nextString() throws IOException
   {
      st.nextToken();
      return (String)st.sval;
   }

   int nextInt() throws IOException
   {
      st.nextToken();
      return (int)st.nval;
   }

   long nextLong() throws IOException
   {
       st.nextToken();
       return (long)st.nval;
   }

   void run() throws IOException
   {
      in = new BufferedReader(new InputStreamReader(System.in));
      st = new StreamTokenizer(in);
      out = new PrintWriter(new OutputStreamWriter(System.out));

      solve();
      out.flush();
   }

   void init(){
       fact[0] = 1;
       fact[1] = 1;
       factrev[0] = 1;
       factrev[1] = 1;
       p[0] = 1;
       p[1] = 1;
       for (int i=2; i<=1000000; i++){
           fact[i] = (i * fact[i-1]) % modulo;
           factrev[i] = reverse(fact[i]) % modulo;
           p[i] = (p[i - 1] + (i - 1) * p[i - 2]) % modulo;
       }
   }

   public static boolean nextPermutation(int[] p) {
        for (int a = p.length - 2; a >= 0; --a)
          if (p[a] < p[a + 1])
            for (int b = p.length - 1;; --b)
              if (p[b] > p[a]) {
                int t = p[a];
                p[a] = p[b];
                p[b] = t;
                for (++a, b = p.length - 1; a < b; ++a, --b) {
                  t = p[a];
                  p[a] = p[b];
                  p[b] = t;
                }
                return true;
              }
        return false;
      }

   long go(int a, int b){
       if (mas[a][b] > 0){
           return mas[a][b];
       } else if (a == 0){
           mas[a][b] = fact[b];
           return fact[b];
       } else if (a == 1){
           if (b == 0){
               mas[1][0] = 1;
               return 1;
           }
           if (b == 1){
               mas[1][1] = 2;
               return 2;
           }
           if (b > 1){
               mas[a][b] = (b * (go(1, b - 1))) % modulo;
               return mas[a][b];
           }
       } else {
           if (b == 0){
               mas[a][b] = (b * (go(a, b - 1))) % modulo;
           }
           mas[a][b] += ((a - 1) * go(a - 2, b)) % modulo;
           mas[a][b] %= modulo;
           return mas[a][b];
       }
       return 0;
   }

    long step(long x, long y){
        if (y==1){
            return x;
        }
        long h = step(x, y >> 1);
        h = (h * h) % modulo;
        if ((y&1)!=0){
            h = (h * x) % modulo;
        }
        return h;
    }

    long reverse(long x){
        return step(x, modulo - 2);
    }

   void solve() throws IOException
   {
       init();
       int n = nextInt();
       mas = new long[n][n];
       int x = 0;
       int y = 0;
       for (int i=0; i<n; i++){
           int q = nextInt();
           if (q == 1){
               x++;
           } else {
               y++;
           }
//         out.print(go(x, y));
       }
       out.print((((p[x] * fact[x + y]) % modulo) * factrev[x]) % modulo);
//     int[] x = new int[n];
//     int[] p = new int[n];
//     for (int i=0; i<n; i++){
//         x[i] = nextInt();
//         p[i] = i;
//     }
//     int k = 0;
//     do {
//         int s = x[p[0]] + x[p[1]] + x[p[2]];
//         int s1 = s;
//         for (int i=3; i<x.length; i++){
//             s = s + x[p[i]] - x[p[i-3]];
//             if (s < s1){
//                 s1  = s;
//             }
//         }
//         if (s1 == 3){
//             k++;
//         }
//     } while (nextPermutation(p));
//     out.print(k);
   }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class DD {
	private static BufferedReader in;

	static final int M = 1000000007;

	public void run() throws IOException {
		int n = Integer.parseInt(in.readLine());
		int m = 0;
		StringTokenizer st = new StringTokenizer(in.readLine());
		for (int i = 0; i < n; i++) {
			if (Integer.parseInt(st.nextToken()) == 1) {
				m++;
			}
		}
		int[] fact = new int[n + 2];
		int[][] cnk = new int[n + 1][n + 1];
		int[][] c1 = new int[n + 1][n + 1];
		int[][] c2 = new int[n + 1][n + 1];
		fact[0] = 1;
		for (int i = 1; i <= n + 1; i++) {
			fact[i] = (int) ((fact[i - 1] * (long) i) % M);
		}
		for (int i = 0; i <= n; i++) {
			cnk[i][0] = cnk[i][i] = 1;
			for (int j = 1; j < i; j++) {
				cnk[i][j] = (cnk[i - 1][j - 1] + cnk[i - 1][j]) % M;
			}
			for (int j = 0; j <= i; j++) {
				c1[i][j] = (int) ((cnk[i][j] * (long) fact[j]) % M);
				c2[i][j] = (int) ((cnk[i][j] * (long) fact[j + 1]) % M);
			}
		}
		int[][] a = new int[n + 1][n + 1];
		a[0][0] = 1;
		for (int i = 1; i <= n; i++) {
			for (int j = 0; j <= i; j++) {
				int jj = i - j;
				if (j <= 1) {
					a[i][j] = fact[i];
					continue;
				}
				for (int k = 0; k <= jj; k++) {
					long c = (c1[jj][k] * 1L * a[i - k - 1][j - 1]) % M;
					long d = (c2[jj][k] * 1L * a[i - k - 2][j - 2]) % M;
					a[i][j] = (int) ((a[i][j] + c + d * (j - 1)) % M);
				}
			}
		}
//		for (int i = 1; i <= n; i++) {
//			for (int j = 0; j <= i; j++) {
//				System.out.print(a[i][j] + " ");
//			}
//			System.out.println();
//		}
		System.out.println(a[n][m]);
	}

	public static void main(String[] args) throws IOException {
		Locale.setDefault(Locale.US);
		in = new BufferedReader(new InputStreamReader(System.in));
		new DD().run();
		in.close();
	}
}


import java.util.*;
import java.io.*;

public class DwithPrecalc {
	FastScanner in;
	PrintWriter out;

	final long mod = 1000_000_000 + 7;

	public void solve() throws IOException {
		int n = in.nextInt();
		int[] a = new int[n];
		int count = 0;
		for (int i = 0; i < n; i++) {
			a[i] = in.nextInt();
			if (a[i] == 2) {
				count++;
			}
		}

		long[] d = new long[n + 1];
		d[0] = 1;
		d[1] = 2;
		for (int i = 2; i <= n; i++) {
			d[i] = (d[i - 1] + (i) * d[i - 2]) % mod;
		}
		long ans = d[n - count - 1];
		for (int i = n - count + 1; i <= n; i++) {
			ans = (ans * i) % mod;
		}
		out.println(ans);
	}

	public void run() {
		try {
			in = new FastScanner();
			out = new PrintWriter(System.out);

			solve();

			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		FastScanner() {
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		boolean hasNext() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					String s = br.readLine();
					if (s == null) {
						return false;
					}
					st = new StringTokenizer(s);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return true;
		}

		String next() {
			while (st == null || !st.hasMoreTokens()) {
				try {
					st = new StringTokenizer(br.readLine());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return st.nextToken();
		}

		int nextInt() {
			return Integer.parseInt(next());
		}

		long nextLong() {
			return Long.parseLong(next());
		}

		double nextDouble() {
			return Double.parseDouble(next());
		}
	}

	public static void main(String[] arg) {
		new DwithPrecalc().run();
	}
}


/*
､ｽ､ﾎｻｨ､｡・､ｫ､ｻ､ﾐ
､｢､ﾈ､ﾏ
ｿﾝ､・・ﾎ､ｬ｡｡､ｽ､ﾎｶｨ､皃ｫ

､ｽ､ﾎﾃ・｡ﾉ｢､鬢ｷ､ﾆ
､ﾄ､ﾊ､ｰ
ﾋｼ､､､ｫ､ﾆ｡｡ﾊﾜ､ｱﾈ｡､ﾃ､ﾆ
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <cstdlib>
#include <utility>
#include <cmath>
using namespace std;
#define ll long long
#define all(x) (x).begin(), (x).end()
#define ayacin ios::sync_with_stdio(false);
#define mod 1000000007
#define yukari 99999999
#define M_PI12 3.141592653
#define Parseedouble long double
#define lson o<<1
#define rson o<<1|1
#define pq priority_queue
bool prime[32333];
int a[105],x[105],y[105],e;
int n,m,len[105],first[105],next[2333];
struct Edge {
    int x,y,f,next;
}edge[2333];
void addedge(int x,int y) {
    edge[e].x = x;edge[e].y = y;edge[e].next = first[x];edge[e].f = min(len[x],len[y]);first[x] = e++;//?条?的流量?相??点中含?数个数的?小?
    edge[e].x = y;edge[e].y = x;edge[e].next = first[y];edge[e].f = 0;first[y] = e++;
}
void init() {
    memset(prime,false,sizeof(prime));
    for(int i = 2;i <= 31622;i++) {
        if(!prime[i]) {
            for(int j = i + i;j <= 31622;j += i)
                prime[j] = true;
        }
    }
    e = 0;
    return;
}
int dis[105];
bool bfs(int s,int t) {
    memset(dis,-1,sizeof(dis));
    dis[s] = 0;
    queue<int> p;
    p.push(s);
    while(!p.empty()) {
        int now = p.front();p.pop();
        //cout<<" now = "<<now<<endl;
        for(int k = first[now];k != -1;k = edge[k].next) {
            if(edge[k].f && dis[edge[k].y] == -1) {
                dis[edge[k].y] = dis[now] + 1;
                if(edge[k].y == t)
                   return true;
                p.push(edge[k].y);
            }
        }
    }
    return false;
}
int dfs(int now,int flow,int t) {
    int f;
    if(now == t) return flow;
    for(int k = first[now];k != -1;k = edge[k].next) {
        if(edge[k].f && dis[edge[k].y] == dis[now] + 1 && (f = dfs(edge[k].y,min(flow,edge[k].f),t))) {
            edge[k].f -= f;
            edge[k^1].f += f;
            return f;
        }
    }
    return 0;
}
int dinic(int s,int t) {
    int flow,ret = 0;
    while(bfs(s,t)) {
        while(flow = dfs(s,23333333,t))
            ret += flow;
    }
    return ret;
}
int solve(int xx) {
    memset(len,0,sizeof(len));
    for(int i = 1;i <= n;i++) {
        while(a[i] % xx == 0) {
            len[i]++;
            a[i] /= xx;
        }
    }
    len[0] = len[n+1] =23333;
    e = 0;
    memset(first,-1,sizeof(first));
    for(int i = 1;i <= m;i++)  {
        if(x[i] % 2 == 1)
            addedge(x[i],y[i]);
        else
            addedge(y[i],x[i]);
    }
    for(int i = 1;i <= n;i+= 2)
        addedge(0,i);
    for(int i = 2;i <= n;i+= 2)
        addedge(i,n+1);
    int ret = dinic(0,n+1);
    return ret;
}

void adde(int x,int y)
{
    edge[e].x = x;edge[e].y = y;edge[e].next = first[x];
    if(x == 0)
        edge[e].f = 1;
    else if(y == n+1)
        edge[e].f = 1;
    else if(a[x] == a[y] && a[x] > 1)
        edge[e].f = 1;
    else
        edge[e].f = 0;
    first[x] = e++;
    edge[e].x = y;edge[e].y = x;edge[e].next = first[y];edge[e].f = 0;first[y] = e++;

}
int main() {
    init();
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++) {
        scanf("%d",&a[i]);
    }
    for(int i = 1;i <= m;i++) {
        scanf("%d%d",&x[i],&y[i]);
    }
    set<int> s;
    int i;
    for(i=1;i<=n;i++){
        int tmp=a[i];
        for(j=2;j*j<=a[i];j++){
            if(!prime[i]&&tmp%j==0){
                while(tmp%j==0){
                    s.insert(j);
                    tmp/=j;
                }
            }
        }
        if(prime(tmp)) s.insert(tmp);
    }
    int ans = 0;
    for (set<int>::iterator it=s.begin();it!=s.end();++it){
        int key=*it;
        ans+=slove(key);
    }
    cout << ans <<endl;
    return 0;
}


/*
､ｽ､ﾎｻｨ､｡・､ｫ､ｻ､ﾐ
､｢､ﾈ､ﾏ
ｿﾝ､・・ﾎ､ｬ｡｡､ｽ､ﾎｶｨ､皃ｫ

､ｽ､ﾎﾃ・｡ﾉ｢､鬢ｷ､ﾆ
､ﾄ､ﾊ､ｰ
ﾋｼ､､､ｫ､ﾆ｡｡ﾊﾜ､ｱﾈ｡､ﾃ､ﾆ
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <cstdlib>
#include <utility>
#include <cmath>
using namespace std;
#define ll long long
#define all(x) (x).begin(), (x).end()
#define ayacin ios::sync_with_stdio(false);
#define mod 1000000007
#define yukari 99999999
#define M_PI12 3.141592653
#define Parseedouble long double
#define lson o<<1
#define rson o<<1|1
#define pq priority_queue
bool prime[32333];
int a[105],x[105],y[105],e;
int n,m,len[105],first[105],next[2333];
struct Edge {
    int x,y,f,next;
}edge[2333];
void addedge(int x,int y) {
    edge[e].x = x;edge[e].y = y;edge[e].next = first[x];edge[e].f = min(len[x],len[y]);first[x] = e++;//?条?的流量?相??点中含?数个数的?小?
    edge[e].x = y;edge[e].y = x;edge[e].next = first[y];edge[e].f = 0;first[y] = e++;
}
void init() {
    memset(prime,false,sizeof(prime));
    for(int i = 2;i <= 31622;i++) {
        if(!prime[i]) {
            for(int j = i + i;j <= 31622;j += i)
                prime[j] = true;
        }
    }
    e = 0;
    return;
}
int dis[105];
bool bfs(int s,int t) {
    memset(dis,-1,sizeof(dis));
    dis[s] = 0;
    queue<int> p;
    p.push(s);
    while(!p.empty()) {
        int now = p.front();p.pop();
        for(int k = first[now];k != -1;k = edge[k].next) {
            if(edge[k].f && dis[edge[k].y] == -1) {
                dis[edge[k].y] = dis[now] + 1;
                if(edge[k].y == t)
                   return true;
                p.push(edge[k].y);
            }
        }
    }
    return false;
}
int dfs(int now,int flow,int t) {
    int f;
    if(now == t) return flow;
    for(int k = first[now];k != -1;k = edge[k].next) {
        if(edge[k].f && dis[edge[k].y] == dis[now] + 1 && (f = dfs(edge[k].y,min(flow,edge[k].f),t))) {
            edge[k].f -= f;
            edge[k^1].f += f;
            return f;
        }
    }
    return 0;
}
int dinic(int s,int t) {
    int flow,ret = 0;
    while(bfs(s,t)) {
        while(flow = dfs(s,23333333,t))
            ret += flow;
    }
    return ret;
}
int solve(int xx) {
    memset(len,0,sizeof(len));
    for(int i = 1;i <= n;i++) {
        while(a[i] % xx == 0) {
            len[i]++;
            a[i] /= xx;
        }
    }
    len[0] = len[n+1] =23333;
    e = 0;
    memset(first,-1,sizeof(first));
    for(int i = 1;i <= m;i++)  {
        if(x[i] % 2 == 1)
            addedge(x[i],y[i]);
        else
            addedge(y[i],x[i]);
    }
    for(int i = 1;i <= n;i+= 2)
        addedge(0,i);
    for(int i = 2;i <= n;i+= 2)
        addedge(i,n+1);
    int ret = dinic(0,n+1);
    return ret;
}

void adde(int x,int y)
{
    edge[e].x = x;edge[e].y = y;edge[e].next = first[x];
    if(x == 0)
        edge[e].f = 1;
    else if(y == n+1)
        edge[e].f = 1;
    else if(a[x] == a[y] && a[x] > 1)
        edge[e].f = 1;
    else
        edge[e].f = 0;
    first[x] = e++;
    edge[e].x = y;edge[e].y = x;edge[e].next = first[y];edge[e].f = 0;first[y] = e++;

}
int main() {
    init();
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++) {
        scanf("%d",&a[i]);
    }
    for(int i = 1;i <= m;i++) {
        scanf("%d%d",&x[i],&y[i]);
    }

    int ans = 0;
    for(int i = 2;i <= 31622;i++) {
        if(!prime[i])
            ans += solve(i);
    }

    for(int i = 1;i <= n;i+= 2)
        adde(0,i);
    for(int i = 2;i <= n;i+= 2)
        adde(i,n+1);
    for(int i = 1;i <= m;i++) {
        if(x[i] % 2 == 1)
            adde(x[i],y[i]);
        else
            adde(y[i],x[i]);
    }
    ans += dinic(0,n+1);
    cout << ans <<endl;
    return 0;
}


#include<bits/stdc++.h>
#define int long long

using namespace std;

const int N = 111;

int readInt ()
{
    bool minus = false;
    int result = 0;
    char ch;
    ch = getchar();
    while (true)
    {
        if (ch == '-') break;
        if (ch >= '0' && ch <= '9') break;
        ch = getchar();
    }
    if (ch == '-') minus = true;
    else result = ch-'0';
    while (true)
    {
        ch = getchar();
        if (ch < '0' || ch > '9') break;
        result = result*10 + (ch - '0');
    }
    if (minus)
        return -result;
    else
        return result;
}
int a[N];
int cost[N][N];
int u, v;
bool used[N];
int mt[N];
int mx[N];
int pos[N];
vector<pair<int, int> > order;
vector<int> g[N];
vector<int> g1, g2;
bool try_kuhn(int v)
{
    if (used[v]) return false;
    used[v] = true;
    for (int to : g[v]) {
        if (mt[to] == -1 || try_kuhn(mt[to])) {
            mt[to] = v;
            return true;
        }
    }
    return false;
}
int col[101];
void bfs(int v)
{
    queue<int> q;
    q.push(v);
    col[v] = 0;
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        for (int to : g[v]) {
            if (col[to] == -1) {
                col[to] = col[v] ^ 1;
                q.push(to);
            }
        }
    }
}
main() {
    int n = readInt(), m = readInt();
    for (int i = 1; i <= n; i++) {
        a[i] = readInt();
    }
    int k = 0;
    for (int i = 1; i <= m; i++) {
        int u = readInt(), v = readInt();
        int gcd = __gcd(a[u], a[v]);
        int w = 0;
        for (int j = 2; j * j <= gcd; j++) {
            while (gcd % j == 0) {
                gcd /= j;
                ++w;
            }
        }
        if (gcd > 1) {
            ++w;
        }
        cost[u][v] = w;
//        order.push_back(make_pair(w, v));
        g[u].push_back(v);
//        g[v].push_back(u);
    }
    fill(col + 1, col + n + 1, -1);
    for (int i = 1; i <= n; i++) {
        if (col[i] == -1)
            bfs(i);
    }
    for (int i = 1; i <= n; i++) {
        if (!col[i]) {
            g1.push_back(i);
            int mm = 0;
            for (int j = 1; j <= n; j++) {
                mm = max(mm, cost[i][j]);
            }
            order.push_back(make_pair(mm, i));
        } else {
            g2.push_back(i);
        }
    }
//    for (int it : g1) {
//        cout << it << " ";
//    }
//    puts("");
//    puts(" --- ");
//    puts("");
//    for (int it : g2) {
//        cout << it << " ";
//    }
    int n1 = n, n2 = n;
    fill(mt + 1, mt + n2 + 1, -1);
    sort(order.rbegin(), order.rend());
//    for ()
    for (auto it : order) {
//        cout << it.first << " " << it.second << "\n";
//        if (_tm[it.second] == -1) {
//            cout << it.second << "\n";
            fill(used + 1, used + n1 + 1, false);
            try_kuhn(it.second);
//        }
    }
//    return 0;
    int ans = 0;
    for (int i : g2) {
        if (mt[i] == -1) continue;
//        cout << "fsf";
        cout << i << " " << mt[i] << " " << cost[mt[i]][i] << "\n";
        ans += cost[mt[i]][i];
    }
//    puts("");
    cout << ans;
}


#include<bits/stdc++.h>
#define int long long

using namespace std;

const int N = 1111;

int readInt ()
{
    bool minus = false;
    int result = 0;
    char ch;
    ch = getchar();
    while (true)
    {
        if (ch == '-') break;
        if (ch >= '0' && ch <= '9') break;
        ch = getchar();
    }
    if (ch == '-') minus = true;
    else result = ch-'0';
    while (true)
    {
        ch = getchar();
        if (ch < '0' || ch > '9') break;
        result = result*10 + (ch - '0');
    }
    if (minus)
        return -result;
    else
        return result;
}
int a[N];
int u, v, ans;
int l[N][N], r[N][N];
vector<int> p[N], g[1234567];
int mt[N];
bool used[N];
bool try_kuhn(int v)
{
    if (used[v]) return false;
    used[v] = true;
//    cout << v << "\n";
    for (int to : g[v]) {
        if (mt[to] == -1 || try_kuhn(mt[to])) {
//            cout << v << " ! " << to << "\n";
//    cout << "saf";
            mt[to] = v;
            return true;
        }
    }
    return false;
}
main() {
    int n = readInt(), m = readInt();
    int sz1 = 0, sz2 = 0;
    for (int i = 1; i <= n; i++) {
        a[i] = readInt();
        int x = a[i];
        for (int j = 2; j * j <= x; j++) {
            while (x % j == 0) {
                x /= j;
                p[i].push_back(j);
            }
        }
        if (x > 1) {
            p[i].push_back(x);
        }
        for (int j = 0; j < p[i].size(); j++) {
            if (i % 2 == 1) {
                l[i][j + 1] = ++sz1;
            } else {
                r[i][j + 1] = ++sz2;
            }
        }
    }
//    cout << sz1 << " " << sz2 << "\n";
    for (int i = 1; i <= m; i++) {
        int u = readInt(), v = readInt();
        if (u % 2 == 0) swap(u, v);
        for (int j = 0; j < p[u].size(); j++) {
            for (int k = 0; k < p[v].size(); k++) {
//                cout << p[u][j] << " - " << p[v][k] << "\n";
                if (p[u][j] == p[v][k]) {
//                    puts("asf");
                    g[l[u][j + 1]].push_back(r[v][k + 1]);
                }
            }
        }
    }
    int ans = 0;
    fill(mt + 1, mt + sz2 + 1, -1);
    for (int i = 1; i <= sz1; i++) {
        fill(used + 1, used + sz1 + 1, false);
        if (try_kuhn(i)) ++ans;
    }
    cout << ans;
}
/**
6 4
16 256 16 16 262144 65536
2 5
5 6
2 3
1 2
ans: 24
**/


#include<bits/stdc++.h>
#define int long long

using namespace std;

const int N = 1111;

int readInt ()
{
    bool minus = false;
    int result = 0;
    char ch;
    ch = getchar();
    while (true)
    {
        if (ch == '-') break;
        if (ch >= '0' && ch <= '9') break;
        ch = getchar();
    }
    if (ch == '-') minus = true;
    else result = ch-'0';
    while (true)
    {
        ch = getchar();
        if (ch < '0' || ch > '9') break;
        result = result*10 + (ch - '0');
    }
    if (minus)
        return -result;
    else
        return result;
}
int a[N];
int u, v, ans;
int l[N][N], r[N][N];
vector<int> p[N], g[N];
int mt[N];
bool used[N];
bool try_kuhn(int v)
{
    if (used[v]) return false;
    used[v] = true;
//    cout << v << "\n";
    for (int to : g[v]) {
        if (mt[to] == -1 || try_kuhn(mt[to])) {
//            cout << v << " ! " << to << "\n";
//    cout << "saf";
            mt[to] = v;
            return true;
        }
    }
    return false;
}
main() {
    int n = readInt(), m = readInt();
    int sz1 = 0, sz2 = 0;
    for (int i = 1; i <= n; i++) {
        a[i] = readInt();
        int x = a[i];
        for (int j = 2; j * j <= x; j++) {
            while (x % j == 0) {
                x /= j;
                p[i].push_back(j);
            }
        }
        if (x > 1) {
            p[i].push_back(x);
        }
        for (int j = 0; j < p[i].size(); j++) {
            if (i % 2 == 1) {
                l[i][j + 1] = ++sz1;
            } else {
                r[i][j + 1] = ++sz2;
            }
        }
    }
    cout << sz1 << " " << sz2 << "\n";
    for (int i = 1; i <= m; i++) {
        int u = readInt(), v = readInt();
        if (u % 2 == 0) swap(u, v);
        for (int j = 0; j < p[u].size(); j++) {
            for (int k = 0; k < p[v].size(); k++) {
//                cout << p[u][j] << " - " << p[v][k] << "\n";
                if (p[u][j] == p[v][k]) {
//                    puts("asf");
                    g[l[u][j + 1]].push_back(r[v][k + 1]);
                }
            }
        }
    }
    int ans = 0;
    fill(mt + 1, mt + sz2 + 1, -1);
    for (int i = 1; i <= sz1; i++) {
        fill(used + 1, used + sz1 + 1, false);
        if (try_kuhn(i)) ++ans;
    }
    cout << ans;
}
/**
6 4
16 256 16 16 262144 65536
2 5
5 6
2 3
1 2
ans: 24
**/


#include<bits/stdc++.h>
#define int long long

using namespace std;

const int N = 111;

int readInt ()
{
    bool minus = false;
    int result = 0;
    char ch;
    ch = getchar();
    while (true)
    {
        if (ch == '-') break;
        if (ch >= '0' && ch <= '9') break;
        ch = getchar();
    }
    if (ch == '-') minus = true;
    else result = ch-'0';
    while (true)
    {
        ch = getchar();
        if (ch < '0' || ch > '9') break;
        result = result*10 + (ch - '0');
    }
    if (minus)
        return -result;
    else
        return result;
}
int a[N];
int cost[N][N];
int u, v;
bool used[N];
int mt[N];
int mx[N];
int pos[N];
vector<pair<int, int> > order;
vector<int> g[N];
bool try_kuhn(int v)
{
    if (used[v]) return false;
    used[v] = true;
    for (int to : g[v]) {
        if (mt[to] == -1 || try_kuhn(mt[to])) {
            mt[to] = v;
            return true;
        }
    }
    return false;
}
main() {
    int n = readInt(), m = readInt();
    for (int i = 1; i <= n; i++) {
        a[i] = readInt();
    }
    int k = 0;
    for (int i = 1; i <= m; i++) {
        int u = readInt(), v = readInt();
        int g = __gcd(a[u], a[v]);
        int w = 0;
        for (int j = 2; j * j <= g; j++) {
            while (g % j == 0) {
                g /= j;
                ++w;
            }
        }
        if (g > 1) {
            ++w;
        }
        if (mx[u] < w) {
            mx[u] = w;
            pos[u] = v;
        }
    }
    for (int i = 1; i <= n; i++) {
        if (!mx[i])
            continue;
        g[i].push_back(pos[i]);
        order.push_back(make_pair(mx[i], i));
    }
    fill(mt + 1, mt + n + 1, -1);
    sort(order.rbegin(), order.rend());
    for (auto it : order) {
        fill(used + 1, used + n + 1, false);
        try_kuhn(it.second);
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        if (mt[i] == -1) continue;
//        cout << "fsf";
        ans += mx[mt[i]];
    }
    cout << ans;
}


#include<bits/stdc++.h>
#define int long long

using namespace std;

const int N = 1111;

int readInt ()
{
    bool minus = false;
    int result = 0;
    char ch;
    ch = getchar();
    while (true)
    {
        if (ch == '-') break;
        if (ch >= '0' && ch <= '9') break;
        ch = getchar();
    }
    if (ch == '-') minus = true;
    else result = ch-'0';
    while (true)
    {
        ch = getchar();
        if (ch < '0' || ch > '9') break;
        result = result*10 + (ch - '0');
    }
    if (minus)
        return -result;
    else
        return result;
}
int a[N];
int u, v, ans;
int l[N][N], r[N][N];
vector<int> p[N], g[N];
int mt[N];
bool used[N];
bool try_kuhn(int v)
{
    if (used[v]) return false;
    used[v] = true;
//    cout << v << "\n";
    for (int to : g[v]) {
        if (mt[to] == -1 || try_kuhn(mt[to])) {
//            cout << v << " ! " << to << "\n";
//    cout << "saf";
            mt[to] = v;
            return true;
        }
    }
    return false;
}
main() {
    int n = readInt(), m = readInt();
    int sz1 = 0, sz2 = 0;
    for (int i = 1; i <= n; i++) {
        a[i] = readInt();
        int x = a[i];
        for (int j = 2; j * j <= x; j++) {
            while (x % j == 0) {
                x /= j;
                p[i].push_back(j);
            }
        }
        if (x > 1) {
            p[i].push_back(x);
        }
        for (int j = 0; j < p[i].size(); j++) {
            if (i % 2 == 1) {
                l[i][j + 1] = ++sz1;
            } else {
                r[i][j + 1] = ++sz2;
            }
        }
    }
//    cout << sz1 << " " << sz2 << "\n";
    for (int i = 1; i <= m; i++) {
        int u = readInt(), v = readInt();
        if (u % 2 == 0) swap(u, v);
        for (int j = 0; j < p[u].size(); j++) {
            for (int k = 0; k < p[v].size(); k++) {
//                cout << p[u][j] << " - " << p[v][k] << "\n";
                if (p[u][j] == p[v][k]) {
//                    puts("asf");
                    g[l[u][j + 1]].push_back(r[v][k + 1]);
                }
            }
        }
    }
    int ans = 0;
    fill(mt + 1, mt + sz2 + 1, -1);
    for (int i = 1; i <= sz1; i++) {
        fill(used + 1, used + sz1 + 1, false);
        if (try_kuhn(i)) ++ans;
    }
    cout << ans;
}
/**
6 4
16 256 16 16 262144 65536
2 5
5 6
2 3
1 2
ans: 24
**/


#include<bits/stdc++.h>
#define int long long

using namespace std;

const int N = 1111;

int readInt ()
{
    bool minus = false;
    int result = 0;
    char ch;
    ch = getchar();
    while (true)
    {
        if (ch == '-') break;
        if (ch >= '0' && ch <= '9') break;
        ch = getchar();
    }
    if (ch == '-') minus = true;
    else result = ch-'0';
    while (true)
    {
        ch = getchar();
        if (ch < '0' || ch > '9') break;
        result = result*10 + (ch - '0');
    }
    if (minus)
        return -result;
    else
        return result;
}
int a[N];
int u, v, ans;
int l[N][N], r[N][N];
vector<int> p[N], g[1234567];
int mt[1234567];
bool used[1234567];
bool try_kuhn(int v)
{
    if (used[v]) return false;
    used[v] = true;
//    cout << v << "\n";
    for (int to : g[v]) {
        if (mt[to] == -1 || try_kuhn(mt[to])) {
//            cout << v << " ! " << to << "\n";
//    cout << "saf";
            mt[to] = v;
            return true;
        }
    }
    return false;
}
main() {
    int n = readInt(), m = readInt();
    int sz1 = 0, sz2 = 0;
    for (int i = 1; i <= n; i++) {
        a[i] = readInt();
        int x = a[i];
        for (int j = 2; j * j <= x; j++) {
            while (x % j == 0) {
                x /= j;
                p[i].push_back(j);
            }
        }
        if (x > 1) {
            p[i].push_back(x);
        }
        for (int j = 0; j < p[i].size(); j++) {
            if (i % 2 == 1) {
                l[i][j + 1] = ++sz1;
            } else {
                r[i][j + 1] = ++sz2;
            }
        }
    }
//    cout << sz1 << " " << sz2 << "\n";
    for (int i = 1; i <= m; i++) {
        int u = readInt(), v = readInt();
        if (u % 2 == 0) swap(u, v);
        for (int j = 0; j < p[u].size(); j++) {
            for (int k = 0; k < p[v].size(); k++) {
//                cout << p[u][j] << " - " << p[v][k] << "\n";
                if (p[u][j] == p[v][k]) {
//                    puts("asf");
                    g[l[u][j + 1]].push_back(r[v][k + 1]);
                }
            }
        }
    }
    int ans = 0;
    fill(mt + 1, mt + sz2 + 1, -1);
    for (int i = 1; i <= sz1; i++) {
        fill(used + 1, used + sz1 + 1, false);
        if (try_kuhn(i)) ++ans;
    }
    cout << ans;
}
/**
6 4
16 256 16 16 262144 65536
2 5
5 6
2 3
1 2
ans: 24
**/


#include<bits/stdc++.h>
#define int long long

using namespace std;

const int N = 111;

int readInt ()
{
    bool minus = false;
    int result = 0;
    char ch;
    ch = getchar();
    while (true)
    {
        if (ch == '-') break;
        if (ch >= '0' && ch <= '9') break;
        ch = getchar();
    }
    if (ch == '-') minus = true;
    else result = ch-'0';
    while (true)
    {
        ch = getchar();
        if (ch < '0' || ch > '9') break;
        result = result*10 + (ch - '0');
    }
    if (minus)
        return -result;
    else
        return result;
}
int a[N];
int cost[N][N];
int u, v;
bool used[N];
int mt[N];
int mx[N];
int pos[N];
vector<pair<int, int> > order;
vector<int> g[N];
vector<int> g1, g2;
bool try_kuhn(int v)
{
    if (used[v]) return false;
    used[v] = true;
    for (int to : g[v]) {
        if (mt[to] == -1 || try_kuhn(mt[to])) {
            mt[to] = v;
            return true;
        }
    }
    return false;
}
int col[101];
void bfs(int v)
{
    queue<int> q;
    q.push(v);
    col[v] = 0;
    while (!q.empty()) {
        int x = q.front();
        q.pop();
        for (int to : g[v]) {
            if (col[to] == -1) {
                col[to] = col[v] ^ 1;
                q.push(to);
            }
        }
    }
}
main() {
    int n = readInt(), m = readInt();
    for (int i = 1; i <= n; i++) {
        a[i] = readInt();
    }
    int k = 0;
    for (int i = 1; i <= m; i++) {
        int u = readInt(), v = readInt();
        int gcd = __gcd(a[u], a[v]);
        int w = 0;
        for (int j = 2; j * j <= gcd; j++) {
            while (gcd % j == 0) {
                gcd /= j;
                ++w;
            }
        }
        if (gcd > 1) {
            ++w;
        }
        cost[u][v] = w;
//        order.push_back(make_pair(w, v));
        g[u].push_back(v);
//        g[v].push_back(u);
    }
    fill(col + 1, col + n + 1, -1);
    for (int i = 1; i <= n; i++) {
        if (col[i] == -1)
            bfs(i);
    }
    for (int i = 1; i <= n; i++) {
        if (!col[i]) {
            g1.push_back(i);
            int mm = 0;
            for (int j = 1; j <= n; j++) {
                mm = max(mm, cost[i][j]);
            }
            order.push_back(make_pair(mm, i));
        } else {
            g2.push_back(i);
        }
    }
//    for (int it : g1) {
//        cout << it << " ";
//    }
//    puts("");
//    puts(" --- ");
//    puts("");
//    for (int it : g2) {
//        cout << it << " ";
//    }
    int n1 = n, n2 = n;
    fill(mt + 1, mt + n2 + 1, -1);
    sort(order.rbegin(), order.rend());
//    for ()
    for (auto it : order) {
//        cout << it.first << " " << it.second << "\n";
//        if (_tm[it.second] == -1) {
//            cout << it.second << "\n";
            fill(used + 1, used + n1 + 1, false);
            try_kuhn(it.second);
//        }
    }
//    return 0;
    int ans = 0;
    for (int i : g2) {
        if (mt[i] == -1) continue;
//        cout << "fsf";
//        cout << i << " " << mt[i] << " " << cost[mt[i]][i] << "\n";
        ans += cost[mt[i]][i];
    }
//    puts("");
    cout << ans;
}


#include<bits/stdc++.h>
#define int long long

using namespace std;

const int N = 111;

int readInt ()
{
    bool minus = false;
    int result = 0;
    char ch;
    ch = getchar();
    while (true)
    {
        if (ch == '-') break;
        if (ch >= '0' && ch <= '9') break;
        ch = getchar();
    }
    if (ch == '-') minus = true;
    else result = ch-'0';
    while (true)
    {
        ch = getchar();
        if (ch < '0' || ch > '9') break;
        result = result*10 + (ch - '0');
    }
    if (minus)
        return -result;
    else
        return result;
}
int a[N];
int cost[N][N];
int u, v;
bool used[N];
int mt[N];
int mx[N];
int pos[N];
vector<pair<int, int> > order;
vector<int> g[N];
bool try_kuhn(int v)
{
    if (used[v]) return false;
    used[v] = true;
    for (int to : g[v]) {
        if (mt[to] == -1 || try_kuhn(mt[to])) {
            mt[to] = v;
            return true;
        }
    }
    return false;
}
main() {
    int n = readInt(), m = readInt();
    for (int i = 1; i <= n; i++) {
        a[i] = readInt();
    }
    int k = 0;
    for (int i = 1; i <= m; i++) {
        int u = readInt(), v = readInt();
        int g = __gcd(a[u], a[v]);
        int w = 0;
        for (int j = 2; j * j <= g; j++) {
            while (g % j == 0) {
                g /= j;
                ++w;
            }
        }
        cost[u][v] = max(cost[u][v], w);
        if (mx[u] < w) {
            mx[u] = w;
            pos[u] = v;
        }
    }
    for (int i = 1; i <= n; i++) {
        if (!mx[i])
            continue;
        g[i].push_back(pos[i]);
        order.push_back(make_pair(mx[i], i));
    }
    fill(mt + 1, mt + n + 1, -1);
    sort(order.rbegin(), order.rend());
    for (auto it : order) {
        fill(used + 1, used + n + 1, false);
        try_kuhn(it.second);
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        if (mt[i] == -1) continue;
//        cout << "fsf";
        ans += mx[i];
    }
    cout << ans;
}


#include<bits/stdc++.h>
#define int long long

using namespace std;

const int N = 111;

int readInt ()
{
    bool minus = false;
    int result = 0;
    char ch;
    ch = getchar();
    while (true)
    {
        if (ch == '-') break;
        if (ch >= '0' && ch <= '9') break;
        ch = getchar();
    }
    if (ch == '-') minus = true;
    else result = ch-'0';
    while (true)
    {
        ch = getchar();
        if (ch < '0' || ch > '9') break;
        result = result*10 + (ch - '0');
    }
    if (minus)
        return -result;
    else
        return result;
}
int a[N];
int cost[N][N];
int u, v;
bool used[N];
int mt[N];
int mx[N];
int pos[N];
vector<pair<int, int> > order;
vector<int> g[N];
bool try_kuhn(int v)
{
    if (used[v]) return false;
    used[v] = true;
    for (int to : g[v]) {
        if (mt[to] == -1 || try_kuhn(mt[to])) {
            mt[to] = v;
            return true;
        }
    }
    return false;
}
main() {
    int n = readInt(), m = readInt();
    for (int i = 1; i <= n; i++) {
        a[i] = readInt();
    }
    int k = 0;
    for (int i = 1; i <= m; i++) {
        int u = readInt(), v = readInt();
        int g = __gcd(a[u], a[v]);
        int w = 0;
        for (int j = 2; j * j <= g; j++) {
            while (g % j == 0) {
                g /= j;
                ++w;
            }
        }
        if (g > 1) {
            ++w;
        }
        if (mx[u] < w) {
            mx[u] = w;
            pos[u] = v;
        }
    }
    for (int i = 1; i <= n; i++) {
        if (!mx[i])
            continue;
        g[i].push_back(pos[i]);
        order.push_back(make_pair(mx[i], i));
    }
    fill(mt + 1, mt + n + 1, -1);
    sort(order.rbegin(), order.rend());
    for (auto it : order) {
        fill(used + 1, used + n + 1, false);
        try_kuhn(it.second);
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        if (mt[i] == -1) continue;
//        cout << "fsf";
        ans += mx[i];
    }
    cout << ans;
}


#include <bits/stdc++.h>
#define fst first
#define snd second
#define mp(x,y) make_pair(x,y)
using namespace std;
typedef long long lli lli;
typedef pair<lli,lli> pii;
const lli MaxN=101,MaxM=100000;

vector<pii> Pi[MaxN],nwady;
lli N,M,A[MaxN],B[MaxN],match[MaxM],GP[MaxN][MaxN];
set<lli>primes;
bool mark[MaxM];
vector<lli>ady[MaxM];

bool dfs(lli u){
    if(mark[u])return 0;
    mark[u]=1;
    lli k,p;
    for(k=0;k<ady[u].size();k++){
        p=ady[u][k];
        if(match[p]==-1||dfs(match[p])){
            match[u]=p;
            match[p]=u;
            return 1;
        }
    }
    return 0;
}
lli bipartimatch(lli Ni){
    lli i,j,p,q;
    for(i=0;i<Ni;i++)match[i]=-1;
    for(i=0;i<Ni;i++){
        if(match[i]==-1){
            for(j=0;j<Ni;j++)mark[j]=0;
            dfs(i);
        }
    }
    for(p=0,i=0;i<Ni;i++)p+=(match[i]!=-1);
    return p/2;
}
lli Prime(lli P){
    lli Ni,i,j,p,q;
    nwady.clear();
    for(i=Ni=0;i<N;i++){
        if(B[i]%P)continue;
        for(p=0;p<Pi[i].size();p++)if(Pi[i][p].fst==P)break;
        p=Pi[i][p].snd;
        for(q=0;q<p;q++)
            nwady.push_back(mp(i,Ni++));
    }
    for(i=0;i<Ni;i++){
        ady[i].clear();
        for(j=0;j<Ni;j++){
            if(GP[nwady[i].fst][nwady[j].fst])
                ady[i].push_back(nwady[j].snd);
        }
    }
    return bipartimatch(Ni);
}

void doprimes(){
    lli i,j,p,q;
    for(i=0;i<N;i++){
        j=2,B[i]=A[i];
        if(A[i]%j==0){
            p=0;
            while(A[i]%j==0)p++,A[i]/=j;
            Pi[i].push_back(mp(j,p));
            primes.insert(j);
        }
        for(j=3;j*j<=A[i];j+=2){
            if(A[i]%j==0){
                p=0;
                while(A[i]%j==0)p++,A[i]/=j;
                Pi[i].push_back(mp(j,p));
                primes.insert(j);
            }
        }
        if(A[i]>1){
            Pi[i].push_back(mp(A[i],1));
            primes.insert(j);
        }
    }
}
int main(){
    lli i,j,p,q,ans=0;
    cin>>N>>M;
    for(i=0;i<N;i++)
        cin>>A[i];
    for(i=0;i<M;i++){
        cin>>p>>q;
        GP[p-1][q-1]=GP[q-1][p-1]=1;
    }
    doprimes();
    for(auto k:primes)
        ans+=Prime(k);
    cout<<ans;
}


#include <bits/stdc++.h>
#define fst first
#define snd second
#define mp(x,y) make_pair(x,y)
using namespace std;
typedef long long int lli;
typedef pair<lli,lli> pii;
const lli MaxN=101,MaxM=100000;

vector<pii> Pi[MaxN],nwady;
lli N,M,A[MaxN],B[MaxN],match[MaxM],GP[MaxN][MaxN];
set<lli>primes;
bool mark[MaxM];
vector<lli>ady[MaxM];

bool dfs(lli u){
    if(mark[u])return 0;
    mark[u]=1;
    lli k,p;
    for(k=0;k<ady[u].size();k++){
        p=ady[u][k];
        if(match[p]==-1||dfs(match[p])){
            match[u]=p;
            match[p]=u;
            return 1;
        }
    }
    return 0;
}
lli bipartimatch(lli Ni){
    lli i,j,p,q;
    for(i=0;i<Ni;i++)match[i]=-1;
    for(i=0;i<Ni;i++){
        if(match[i]==-1){
            for(j=0;j<Ni;j++)mark[j]=0;
            dfs(i);
        }
    }
    for(p=0,i=0;i<Ni;i++)p+=(match[i]!=-1);
    return p/2;
}
lli Prime(lli P){
    lli Ni,i,j,p,q;
    nwady.clear();
    for(i=Ni=0;i<N;i++){
        if(B[i]%P)continue;
        for(p=0;p<Pi[i].size();p++)if(Pi[i][p].fst==P)break;
        p=Pi[i][p].snd;
        for(q=0;q<p;q++)
            nwady.push_back(mp(i,Ni++));
    }
    for(i=0;i<Ni;i++){
        ady[i].clear();
        for(j=0;j<Ni;j++){
            if(GP[nwady[i].fst][nwady[j].fst])
                ady[i].push_back(nwady[j].snd);
        }
    }
    return bipartimatch(Ni);
}

void doprimes(){
    lli i,j,p,q;
    for(i=0;i<N;i++){
        j=2,B[i]=A[i];
        if(A[i]%j==0){
            p=0;
            while(A[i]%j==0)p++,A[i]/=j;
            Pi[i].push_back(mp(j,p));
            primes.insert(j);
        }
        for(j=3;j*j<=A[i];j+=2){
            if(A[i]%j==0){
                p=0;
                while(A[i]%j==0)p++,A[i]/=j;
                Pi[i].push_back(mp(j,p));
                primes.insert(j);
            }
        }
        if(A[i]>1){
            Pi[i].push_back(mp(A[i],1));
            primes.insert(j);
        }
    }
}
int main(){
    lli i,j,p,q,ans=0;
    cin>>N>>M;
    for(i=0;i<N;i++)
        cin>>A[i];
    for(i=0;i<M;i++){
        cin>>p>>q;
        GP[p-1][q-1]=GP[q-1][p-1]=1;
    }
    doprimes();
    for(auto k:primes)
        ans+=Prime(k);
    cout<<ans;
}


#include <bits/stdc++.h>
#define fst first
#define snd second
#define mp(x,y) make_pair(x,y)
using namespace std;
typedef long long int lli;
typedef pair<lli,lli> pii;
const lli MaxN=101,MaxM=100000;

vector<pii> Pi[MaxN],nwady;
lli N,M,A[MaxN],B[MaxN],match[MaxM],GP[MaxN][MaxN];
bool mark[MaxM];
vector<lli>ady[MaxM],primes;

bool dfs(lli u){
    if(mark[u])return 0;
    mark[u]=1;
    lli k,p;
    for(k=0;k<ady[u].size();k++){
        p=ady[u][k];
        if(match[p]==-1||dfs(match[p])){
            match[u]=p;
            match[p]=u;
            return 1;
        }
    }
    return 0;
}
lli bipartimatch(lli Ni){
    lli i,j,p,q;
    memset(match,-1,sizeof match);
    for(i=0;i<Ni;i++){
        if(match[i]==-1){
            memset(mark,false,sizeof mark);
            dfs(i);
        }
    }
    for(p=0,i=0;i<Ni;i++){
        if(match[i]!=-1){
            match[match[i]]=-1;
            p++;
        }
    }
    return p;
}
lli Prime(lli P){
    lli Ni,i,j,p,q;
    nwady.clear();
    for(i=Ni=0;i<N;i++){
        if(B[i]%P)continue;
        for(p=0;p<Pi[i].size();p++)if(Pi[i][p].fst==P)break;
        p=Pi[i][p].snd;
        for(q=0;q<p;q++)
            nwady.push_back(mp(i,Ni++));
    }
    for(i=0;i<Ni;i++){
        ady[i].clear();
        for(j=0;j<Ni;j++){
            if(GP[nwady[i].fst][nwady[j].fst])
                ady[i].push_back(nwady[j].snd);
        }
    }
    return bipartimatch(Ni);
}

void doprimes(){
    lli i,j,p,q;
    for(i=0;i<N;i++){
        j=2,B[i]=A[i];
        if(A[i]%j==0){
            p=0;
            while(A[i]%j==0)p++,A[i]/=j;
            Pi[i].push_back(mp(j,p));
            primes.push_back(j);
        }
        for(j=3;j*j<=A[i];j+=2){
            if(A[i]%j==0){
                p=0;
                while(A[i]%j==0)p++,A[i]/=j;
                Pi[i].push_back(mp(j,p));
                primes.push_back(j);
            }
        }
        if(A[i]>1){
            Pi[i].push_back(mp(A[i],1));
            primes.push_back(A[i]);
        }
    }
}
int main(){
    lli i,j,p,q,ans=0,k;
    cin>>N>>M;
    for(i=0;i<N;i++)
        cin>>A[i];
    for(i=0;i<M;i++){
        cin>>p>>q;
        GP[p-1][q-1]=GP[q-1][p-1]=1;
    }
    doprimes();
    sort(primes.begin(),primes.end());
    for(i=0;i<primes.size();){
        k=primes[i];
        while(i<primes.size()&&primes[i]==k)i++;
        ans+=Prime(k);
    }
    cout<<ans;
}


#include <bits/stdc++.h>
#define fst first
#define snd second
#define mp(x,y) make_pair(x,y)
using namespace std;
const lli MaxN=101,MaxM=100000;
typedef long long lli lli;
typedef pair<lli,lli> pii;
vector<pii> Pi[MaxN],nwady;
lli N,M,A[MaxN],B[MaxN],match[MaxM],GP[MaxN][MaxN];
set<lli>primes;
bool mark[MaxM];
vector<lli>ady[MaxM];

bool dfs(lli u){
    if(mark[u])return 0;
    mark[u]=1;
    lli k,p;
    for(k=0;k<ady[u].size();k++){
        p=ady[u][k];
        if(match[p]==-1||dfs(match[p])){
            match[u]=p;
            match[p]=u;
            return 1;
        }
    }
    return 0;
}
lli bipartimatch(lli Ni){
    lli i,j,p,q;
    for(i=0;i<Ni;i++)match[i]=-1;
    for(i=0;i<Ni;i++){
        if(match[i]==-1){
            for(j=0;j<Ni;j++)mark[j]=0;
            dfs(i);
        }
    }
    for(p=0,i=0;i<Ni;i++)p+=(match[i]!=-1);
    return p/2;
}
lli Prime(lli P){
    lli Ni,i,j,p,q;
    nwady.clear();
    for(i=Ni=0;i<N;i++){
        if(B[i]%P)continue;
        for(p=0;p<Pi[i].size();p++)if(Pi[i][p].fst==P)break;
        p=Pi[i][p].snd;
        for(q=0;q<p;q++)
            nwady.push_back(mp(i,Ni++));
    }
    for(i=0;i<Ni;i++){
        ady[i].clear();
        for(j=0;j<Ni;j++){
            if(GP[nwady[i].fst][nwady[j].fst])
                ady[i].push_back(nwady[j].snd);
        }
    }
    return bipartimatch(Ni);
}

void doprimes(){
    lli i,j,p,q;
    for(i=0;i<N;i++){
        j=2,B[i]=A[i];
        if(A[i]%j==0){
            p=0;
            while(A[i]%j==0)p++,A[i]/=j;
            Pi[i].push_back(mp(j,p));
            primes.insert(j);
        }
        for(j=3;j*j<=A[i];j+=2){
            if(A[i]%j==0){
                p=0;
                while(A[i]%j==0)p++,A[i]/=j;
                Pi[i].push_back(mp(j,p));
                primes.insert(j);
            }
        }
        if(A[i]>1){
            Pi[i].push_back(mp(A[i],1));
            primes.insert(j);
        }
    }
}
int main(){
    lli i,j,p,q,ans=0;
    cin>>N>>M;
    for(i=0;i<N;i++)
        cin>>A[i];
    for(i=0;i<M;i++){
        cin>>p>>q;
        GP[p-1][q-1]=GP[q-1][p-1]=1;
    }
    doprimes();
    for(auto k:primes)
        ans+=Prime(k);
    cout<<ans;
}


#include <bits/stdc++.h>
#define fst first
#define snd second
#define mp(x,y) make_pair(x,y)
using namespace std;
const int MaxN=101,MaxM=100000;
typedef pair<int,int> pii;
vector<pii> Pi[MaxN],nwady;
int N,M,A[MaxN],B[MaxN],match[MaxM],GP[MaxN][MaxN];
set<int>primes;
bool mark[MaxM];
vector<int>ady[MaxM];

bool dfs(int u){
    if(mark[u])return 0;
    mark[u]=1;
    int k,p;
    for(k=0;k<ady[u].size();k++){
        p=ady[u][k];
        if(match[p]==-1||dfs(match[p])){
            match[u]=p;
            match[p]=u;
            return 1;
        }
    }
    return 0;
}
int bipartimatch(int Ni){
    int i,j,p,q;
    for(i=0;i<Ni;i++)match[i]=-1;
    for(i=0;i<Ni;i++){
        if(match[i]==-1){
            for(j=0;j<Ni;j++)mark[j]=0;
            dfs(i);
        }
    }
    for(p=0,i=0;i<Ni;i++)p+=(match[i]!=-1);
    return p/2;
}
int Prime(int P){
    int Ni,i,j,p,q;
    nwady.clear();
    for(i=Ni=0;i<N;i++){
        if(B[i]%P)continue;
        for(p=0;p<Pi[i].size();p++)if(Pi[i][p].fst==P)break;
        p=Pi[i][p].snd;
        for(q=0;q<p;q++)
            nwady.push_back(mp(i,Ni++));
    }
    for(i=0;i<Ni;i++){
        ady[i].clear();
        for(j=0;j<Ni;j++){
            if(GP[nwady[i].fst][nwady[j].fst])
                ady[i].push_back(nwady[j].snd);
        }
    }
    return bipartimatch(Ni);
}

void doprimes(){
    int i,j,p,q;
    for(i=0;i<N;i++){
        j=2,B[i]=A[i];
        if(A[i]%j==0){
            p=0;
            while(A[i]%j==0)p++,A[i]/=j;
            Pi[i].push_back(mp(j,p));
            primes.insert(j);
        }
        for(j=3;j*j<=A[i];j+=2){
            if(A[i]%j==0){
                p=0;
                while(A[i]%j==0)p++,A[i]/=j;
                Pi[i].push_back(mp(j,p));
                primes.insert(j);
            }
        }
        if(A[i]>1){
            Pi[i].push_back(mp(A[i],1));
            primes.insert(j);
        }
    }
}
int main(){
    int i,j,p,q,ans=0;
    cin>>N>>M;
    for(i=0;i<N;i++)
        cin>>A[i];
    for(i=0;i<M;i++){
        cin>>p>>q;
        GP[p-1][q-1]=GP[q-1][p-1]=1;
    }
    doprimes();
    for(auto k:primes)
        ans+=Prime(k);
    cout<<ans;
}


#include <bits/stdc++.h>
#define fst first
#define snd second
#define mp(x,y) make_pair(x,y)
using namespace std;
typedef long long int lli;
typedef pair<lli,lli> pii;
const lli MaxN=101,MaxM=100000;

vector<pii> Pi[MaxN],nwady;
lli N,M,A[MaxN],B[MaxN],match[MaxM],GP[MaxN][MaxN];
bool mark[MaxM];
vector<lli>ady[MaxM],primes;

bool dfs(lli u){
    if(mark[u])return 0;
    mark[u]=1;
    lli k,p;
    for(k=0;k<ady[u].size();k++){
        p=ady[u][k];
        if(match[p]==-1||dfs(match[p])){
            match[u]=p;
            match[p]=u;
            return 1;
        }
    }
    return 0;
}
lli bipartimatch(lli Ni){
    lli i,j,p,q;
    memset(match,-1,sizeof match);
    for(i=0;i<Ni;i++){
        if(match[i]==-1){
            memset(mark,false,sizeof mark);
            dfs(i);
        }
    }
    for(p=0,i=0;i<Ni;i++){
        if(match[i]!=-1){
            match[match[i]]=-1;
            p++;
        }
    }
    return p;
}
lli Prime(lli P){
    lli Ni,i,j,p,q;
    nwady.clear();
    for(i=Ni=0;i<N;i++){
        if(B[i]%P)continue;
        for(p=0;p<Pi[i].size();p++)if(Pi[i][p].fst==P)break;
        p=Pi[i][p].snd;
        for(q=0;q<p;q++)
            nwady.push_back(mp(i,Ni++));
    }
    for(i=0;i<Ni;i++){
        ady[i].clear();
        for(j=0;j<Ni;j++){
            if(GP[nwady[i].fst][nwady[j].fst])
                ady[i].push_back(nwady[j].snd);
        }
    }
    return bipartimatch(Ni);
}

void doprimes(){
    lli i,j,p,q;
    for(i=0;i<N;i++){
        j=2,B[i]=A[i];
        if(A[i]%j==0){
            p=0;
            while(A[i]%j==0)p++,A[i]/=j;
            Pi[i].push_back(mp(j,p));
            primes.push_back(j);
        }
        for(j=3;j*j<=A[i];j+=2){
            if(A[i]%j==0){
                p=0;
                while(A[i]%j==0)p++,A[i]/=j;
                Pi[i].push_back(mp(j,p));
                primes.push_back(j);
            }
        }
        if(A[i]>1){
            Pi[i].push_back(mp(A[i],1));
            primes.push_back(j);
        }
    }
}
int main(){
    lli i,j,p,q,ans=0,k;
    cin>>N>>M;
    for(i=0;i<N;i++)
        cin>>A[i];
    for(i=0;i<M;i++){
        cin>>p>>q;
        GP[p-1][q-1]=GP[q-1][p-1]=1;
    }
    doprimes();
    sort(primes.begin(),primes.end());
    for(i=0;i<primes.size();){
        k=primes[i];
        while(i<primes.size()&&primes[i]==k)i++;
        ans+=Prime(k);
    }
    cout<<ans;
}


#include <bits/stdc++.h>
#define fst first
#define snd second
#define mp(x,y) make_pair(x,y)
using namespace std;
typedef long long int lli;
typedef pair<lli,lli> pii;
const lli MaxN=101,MaxM=100000;

vector<pii> Pi[MaxN],nwady;
lli N,M,A[MaxN],B[MaxN],match[MaxM],GP[MaxN][MaxN];
bool mark[MaxM];
vector<lli>ady[MaxM],primes;

bool dfs(lli u){
    if(mark[u])return 0;
    mark[u]=1;
    lli k,p;
    for(k=0;k<ady[u].size();k++){
        p=ady[u][k];
        if(match[p]==-1||dfs(match[p])){
            match[u]=p;
            match[p]=u;
            return 1;
        }
    }
    return 0;
}
lli bipartimatch(lli Ni){
    lli i,j,p,q;
    for(i=0;i<Ni;i++)match[i]=-1;
    for(i=0;i<Ni;i++){
        if(match[i]==-1){
            memset(mark,false,sizeof mark);
            dfs(i);
        }
    }
    for(p=0,i=0;i<Ni;i++){
        if(match[i]!=-1){
            match[match[i]]=-1;
            p++;
        }
    }
    return p;
}
lli Prime(lli P){
    lli Ni,i,j,p,q;
    nwady.clear();
    for(i=Ni=0;i<N;i++){
        if(B[i]%P)continue;
        for(p=0;p<Pi[i].size();p++)if(Pi[i][p].fst==P)break;
        p=Pi[i][p].snd;
        for(q=0;q<p;q++)
            nwady.push_back(mp(i,Ni++));
    }
    for(i=0;i<Ni;i++){
        ady[i].clear();
        for(j=0;j<Ni;j++){
            if(GP[nwady[i].fst][nwady[j].fst])
                ady[i].push_back(nwady[j].snd);
        }
    }
    return bipartimatch(Ni);
}

void doprimes(){
    lli i,j,p,q;
    for(i=0;i<N;i++){
        j=2,B[i]=A[i];
        if(A[i]%j==0){
            p=0;
            while(A[i]%j==0)p++,A[i]/=j;
            Pi[i].push_back(mp(j,p));
            primes.push_back(j);
        }
        for(j=3;j*j<=A[i];j+=2){
            if(A[i]%j==0){
                p=0;
                while(A[i]%j==0)p++,A[i]/=j;
                Pi[i].push_back(mp(j,p));
                primes.push_back(j);
            }
        }
        if(A[i]>1){
            Pi[i].push_back(mp(A[i],1));
            primes.push_back(j);
        }
    }
}
int main(){
    lli i,j,p,q,ans=0,k;
    cin>>N>>M;
    for(i=0;i<N;i++)
        cin>>A[i];
    for(i=0;i<M;i++){
        cin>>p>>q;
        GP[p-1][q-1]=GP[q-1][p-1]=1;
    }
    doprimes();
    sort(primes.begin(),primes.end());
    for(i=0;i<primes.size();){
        k=primes[i];
        while(i<primes.size()&&primes[i]==k)i++;
        ans+=Prime(k);
    }
    cout<<ans;
}


#include <bits/stdc++.h>
#define fst first
#define snd second
#define mp(x,y) make_pair(x,y)
using namespace std;
const int MaxN=101;
typedef pair<int,int> pii;
vector<pii> Pi[MaxN],nwady;
int N,M,A[MaxN],B[MaxN],match[MaxN*100],GP[MaxN][MaxN];
set<int>primes;
bool mark[MaxN*100];
vector<int>ady[MaxN*100];

bool dfs(int u){
    if(mark[u])return 0;
    mark[u]=1;
    int k,p;
    for(k=0;k<ady[u].size();k++){
        p=ady[u][k];
        if(match[p]==-1||dfs(match[p])){
            match[u]=p;
            match[p]=u;
            return 1;
        }
    }
    return 0;
}
int bipartimatch(int Ni){
    int i,j,p,q;
    for(i=0;i<Ni;i++)match[i]=-1;
    for(i=0;i<Ni;i++){
        if(match[i]==-1){
            for(j=0;j<Ni;j++)mark[j]=0;
            dfs(i);
        }
    }
    for(p=0,i=0;i<Ni;i++)p+=(match[i]!=-1);
    return p/2;
}
int Prime(int P){
    int Ni,i,j,p,q;
    nwady.clear();
    for(i=Ni=0;i<N;i++){
        if(B[i]%P)continue;
        for(p=0;p<Pi[i].size();p++)if(Pi[i][p].fst==P)break;
        p=Pi[i][p].snd;
        for(q=0;q<p;q++)
            nwady.push_back(mp(i,Ni++));
    }
    for(i=0;i<Ni;i++){
        ady[i].clear();
        for(j=0;j<Ni;j++){
            if(GP[nwady[i].fst][nwady[j].fst])
                ady[i].push_back(nwady[j].snd);
        }
    }
    return bipartimatch(Ni);
}

void doprimes(){
    int i,j,p,q;
    for(i=0;i<N;i++){
        j=2,B[i]=A[i];
        if(A[i]%j==0){
            p=0;
            while(A[i]%j==0)p++,A[i]/=j;
            Pi[i].push_back(mp(j,p));
            primes.insert(j);
        }
        for(j=3;j*j<=A[i];j+=2){
            if(A[i]%j==0){
                p=0;
                while(A[i]%j==0)p++,A[i]/=j;
                Pi[i].push_back(mp(j,p));
                primes.insert(j);
            }
        }
        if(A[i]>1){
            Pi[i].push_back(mp(A[i],1));
            primes.insert(j);
        }
    }
}
int main(){
    cin.tie(0),ios_base::sync_with_stdio(0);
    int i,j,p,q,ans=0;
    cin>>N>>M;
    for(i=0;i<N;i++)
        cin>>A[i];
    for(i=0;i<M;i++){
        cin>>p>>q;
        GP[p-1][q-1]=GP[q-1][p-1]=1;
    }
    doprimes();
    for(auto k:primes)
        ans+=Prime(k);
    cout<<ans;
}


#include <bits/stdc++.h>
#define fst first
#define snd second
#define mp(x,y) make_pair(x,y)
using namespace std;
typedef long long int lli;
typedef pair<lli,lli> pii;
const lli MaxN=101,MaxM=100000;

vector<pii> Pi[MaxN],nwady;
lli N,M,A[MaxN],B[MaxN],match[MaxM],GP[MaxN][MaxN];
bool mark[MaxM];
vector<lli>ady[MaxM],primes;

bool dfs(lli u){
    if(mark[u])return 0;
    mark[u]=1;
    lli k,p;
    for(k=0;k<ady[u].size();k++){
        p=ady[u][k];
        if(match[p]==-1||dfs(match[p])){
            match[u]=p;
            match[p]=u;
            return 1;
        }
    }
    return 0;
}
lli bipartimatch(lli Ni){
    lli i,j,p,q;
    for(i=0;i<Ni;i++)match[i]=-1;
    for(i=0;i<Ni;i++){
        if(match[i]==-1){
            memset(mark,false,sizeof mark);
            dfs(i);
        }
    }
    for(p=0,i=0;i<Ni;i++){
        if(match[i]!=-1){
            match[match[i]]=-1;
            p++;
        }
    }
    return p;
}
lli Prime(lli P){
    lli Ni,i,j,p,q;
    nwady.clear();
    for(i=Ni=0;i<N;i++){
        if(B[i]%P)continue;
        for(p=0;p<Pi[i].size();p++)if(Pi[i][p].fst==P)break;
        p=Pi[i][p].snd;
        for(q=0;q<p;q++)
            nwady.push_back(mp(i,Ni++));
    }
    for(i=0;i<Ni;i++){
        ady[i].clear();
        for(j=0;j<Ni;j++){
            if(GP[nwady[i].fst][nwady[j].fst])
                ady[i].push_back(nwady[j].snd);
        }
    }
    return bipartimatch(Ni);
}

void doprimes(){
    lli i,j,p,q;
    for(i=0;i<N;i++){
        j=2,B[i]=A[i];
        if(A[i]%j==0){
            p=0;
            while(A[i]%j==0)p++,A[i]/=j;
            Pi[i].push_back(mp(j,p));
            primes.push_back(j);
        }
        for(j=3;j*j<=A[i];j+=2){
            if(A[i]%j==0){
                p=0;
                while(A[i]%j==0)p++,A[i]/=j;
                Pi[i].push_back(mp(j,p));
                primes.push_back(j);
            }
        }
        if(A[i]>1){
            Pi[i].push_back(mp(A[i],1));
            primes.push_back(j);
        }
    }
}
int main(){
    lli i,j,p,q,ans=0;
    cin>>N>>M;
    for(i=0;i<N;i++)
        cin>>A[i];
    for(i=0;i<M;i++){
        cin>>p>>q;
        GP[p-1][q-1]=GP[q-1][p-1]=1;
    }
    doprimes();
    sort(primes.begin(),primes.end());
    for(i=0;i<primes.size();){
        k=primes[i];
        while(i<primes.size()&&primes[i]==k)i++;
        ans+=Prime(k);
    }
    cout<<ans;
}


#include<iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <fstream>

using namespace std;

typedef vector < vector <int> > graph;

class Flow {
    class Edge {
      public:
        int to, cap, flow, rev_edge;
        Edge() {}
        Edge(int to, int cap, int rev_edge) {
            this->to = to;
            this->cap = cap;
            this->flow = 0;
            this->rev_edge = rev_edge;
        }
    };
    public:
        vector < vector < Edge> > graph;
        vector < vector < int > > divisors;
        vector < int > ptr, dist, used, numbers, vertex;
        int n, m;
        int start, end;
        bool bfs(int start, int end, int min_cap) {
            dist.assign(n + 1, n + 1);
            dist[start] = 0;
            queue <int> q;
            q.push(start);
            while (!q.empty()) {
                int ver = q.front(); q.pop();
                for (Edge x : graph[ver]) {
                    if (x.cap < min_cap || x.cap == 0) {
                        continue;
                    }
                    if (dist[ver] + 1 < dist[x.to]) {
                        dist[x.to] = dist[ver] + 1;
                        q.push(x.to);
                    }
                }
            }
            return dist[end] < n + 1;
        }
        int dfs(int ver, int end, int min_cap, int cur_flow) {
            if (ver == end || cur_flow == 0) {
                return cur_flow;
            }
            for (; ptr[ver] < (int)graph[ver].size(); ++ptr[ver]) {
                Edge &x = graph[ver][ptr[ver]];
                if (x.cap < min_cap || dist[ver] + 1 != dist[x.to]) {
                    continue;
                }
                int flow_up = dfs(x.to, end, min_cap, min(cur_flow, x.cap));
                if (flow_up == 0) {
                    continue;
                } else {
                    x.cap -= flow_up;
                    graph[x.to][x.rev_edge].cap += flow_up;
                    if (x.cap == 0) {
                        ++ptr[ver];
                    }
                    return flow_up;
                }
            }
            return 0;
        }
        void init() {
            int from, to, cap, tn, tm;
            cin >> tn >> tm;
            vertex.resize(tn);
            numbers.resize(tn);
            divisors.resize(tn);
            for (int i = 0; i < tn; ++i) {
                cin >> numbers[i];
                for (int j = 2; numbers[i] > 1 && j < 32000; ++j) {
                    while (numbers[i] % j == 0) {
                        numbers[i] /= j;
                        divisors[i].push_back(j);
                    }
                }
                if (numbers[i] > 1) {
                    divisors[i].push_back(numbers[i]);
                }
            }
            start = 1;
            vertex[0] = 2;
            for (int i = 1; i < tn; ++i) {
                vertex[i] = vertex[i - 1] + divisors[i - 1].size();
            }
            graph.resize(vertex[tn - 1] + divisors[tn - 1].size() + 2);
            for (int i = 0; i < tm; ++i) {
                cin >> from >> to; from--; to--;
                for (int d1 = 0; d1 < divisors[from].size(); ++d1) {
                    for (int d2 = 0; d2 < divisors[to].size(); ++d2) {
                        if (divisors[from][d1] != divisors[to][d2]) {
                            continue;
                        }
                        graph[vertex[from] + d1].push_back(
                                    Edge(vertex[to] + d2, 1, graph[vertex[to] + d2].size()));
                        graph[vertex[to] + d2].push_back(
                                    Edge(vertex[from] + d1, 0, graph[vertex[from] + d1].size() - 1));
                    }
                }
            }
            end = vertex[tn - 1] + divisors[tn - 1].size();
            used.resize(end + 1, false);
            used[start] = used[end] = true;
            for (int i = 2; i < end; ++i) {
                if (!used[i]) {
                    add_edges(i, 1, start, end);
                }
            }
            n = end;
            /*
            for (int i = 0; i < m; ++i) {
                cin >> from >> to >> cap;
                graph[from].push_back(Edge(to, cap, graph[to].size()));
                graph[to].push_back(Edge(from, 0, graph[from].size() - 1));
            } */
        }
        void add_edges(int ve, int ev, int st, int en) {
            used[ve] = true;
            if (ev) {
                graph[st].push_back(Edge(ve, 1, graph[ve].size()));
                graph[ve].push_back(Edge(st, 0, graph[st].size() - 1));
            } else {
                graph[ve].push_back(Edge(en, 1, graph[en].size()));
                graph[en].push_back(Edge(ve, 0, graph[ve].size() - 1));
            }
            for (Edge x : graph[ve]) {
                if (!used[x.to]) {
                    add_edges(x.to, ev ^ 1, st, en);
                }
            }
        }
        long long solve() {
            long long answer = 0;
            int push = 1;
            int MAX = 0;
            for (int i = 1; i <= n; ++i) {
                for (Edge x : graph[i]) {
                    if (x.cap > MAX) {
                        MAX = x.cap;
                    }
                }
            }
            while (push <= MAX) {
                push <<= 1;
            }
            push >>= 1;
            while (push) {
                if (!bfs(start, end, push)) {
                    push >>= 1;
                    continue;
                }
                bool was_update = true;
                ptr.assign(n + 1, 0);
                do {
                    int flow_update = dfs(start, end, push, MAX);
                    if (!flow_update) {
                        was_update = false;
                    }
                    answer += flow_update;
                } while (was_update);
            }
            return answer;
        }

};

void solve() {
    Flow solver = Flow();
    solver.init();
    cout << solver.solve();
}

int main()
{
  //  freopen("input", "r", stdin);
  //  freopen("output", "w", stdout);
  //  ios_base::sync_with_stdio(false);
 //   cin.tie(NULL);
    solve();
    return 0;
}


#include<iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <fstream>

using namespace std;

typedef vector < vector <int> > graph;

class Flow {
    class Edge {
    public:
        int to, cap, flow, rev_edge;
        Edge() {}
        Edge(int to, int cap, int rev_edge) {
            this->to = to;
            this->cap = cap;
            this->flow = 0;
            this->rev_edge = rev_edge;
        }
    };
public:
    vector < vector < Edge> > graph;
    vector < vector <int> > graph_base;
    vector < vector < int > > divisors;
    vector < int > ptr, dist, used, numbers, vertex, connect;
    int n, m;
    int start, end;
    bool bfs(int start, int end, int min_cap) {
        dist.assign(n + 1, n + 1);
        dist[start] = 0;
        queue <int> q;
        q.push(start);
        while (!q.empty()) {
            int ver = q.front(); q.pop();
            for (Edge x : graph[ver]) {
                if (x.cap < min_cap || x.cap == 0) {
                    continue;
                }
                if (dist[ver] + 1 < dist[x.to]) {
                    dist[x.to] = dist[ver] + 1;
                    q.push(x.to);
                }
            }
        }
        return dist[end] < n + 1;
    }
    int dfs(int ver, int end, int min_cap, int cur_flow) {
        if (ver == end || cur_flow == 0) {
            return cur_flow;
        }
        for (; ptr[ver] < (int)graph[ver].size(); ++ptr[ver]) {
            Edge &x = graph[ver][ptr[ver]];
            if (x.cap < min_cap || dist[ver] + 1 != dist[x.to]) {
                continue;
            }
            int flow_up = dfs(x.to, end, min_cap, min(cur_flow, x.cap));
            if (flow_up == 0) {
                continue;
            } else {
                x.cap -= flow_up;
                graph[x.to][x.rev_edge].cap += flow_up;
                if (x.cap == 0) {
                    ++ptr[ver];
                }
                return flow_up;
            }
        }
        return 0;
    }
    void init2() {
        cin >> n >> m;
        int from, to, cap;
        graph.resize(n + 2);
        for (int i = 0; i < m; ++i) {
            cin >> from >> to >> cap;
            graph[from].push_back(Edge(to, cap, graph[to].size()));
            graph[to].push_back(Edge(from, cap, graph[from].size() - 1));
        }
    }

    void init() {
        unsigned int from, to;
        int cap, tn, tm;
        cin >> tn >> tm;
        divisors.resize(tn);
        vertex.resize(tn);
        numbers.resize(tn);
        connect.resize(tn + 1);
        graph_base.resize(tn + 1);
        for (int i = 0; i < tn; ++i) {
            cin >> numbers[i];
            for (int j = 2; numbers[i] > 1 && j < 32000; ++j) {
                while (numbers[i] % j == 0) {
                    numbers[i] /= j;
                    divisors[i].push_back(j);
                }
            }
            if (numbers[i] > 1) {
                divisors[i].push_back(numbers[i]);
            }
        }
        start = 1;
        vertex[0] = 2;
        for (int i = 1; i < tn; ++i) {
            vertex[i] = vertex[i - 1] + divisors[i - 1].size();
        }
        end = vertex[tn - 1] + divisors[tn - 1].size();
        for (int i = 0; i < tm; ++i) {
            cin >> from >> to;
            graph_base[from].push_back(to);
            graph_base[to].push_back(from);
        }
        used.resize(tn + 1, false);
        for (int i = 1; i <= tn; ++i) {
            if (!used[i]) {
                split(i, 0);
            }
        }
        graph.resize(end + 1);
        for (int i = 1; i <= tn; ++i) {
            from = i - 1;
            if (connect[i]) {
                for (int d1 = 0; d1 < divisors[from].size(); ++d1) {
                    graph[start].push_back(Edge(vertex[from] + d1, 1, graph[vertex[from] + d1].size()));
                    graph[vertex[from] + d1].push_back(Edge(start, 0, graph[start].size() - 1));
                }
                for (int x : graph_base[i]) {
                    to = x - 1;
                    for (int d1 = 0; d1 < divisors[from].size(); ++d1) {
                        for (int d2 = 0; d2 < divisors[to].size(); ++d2) {
                            graph[vertex[from] + d1].push_back(
                                        Edge(vertex[to] + d2, 1, graph[vertex[to] + d2].size()));
                            graph[vertex[to] + d2].push_back(
                                        Edge(vertex[from] + d1, 0, graph[vertex[from] + d1].size() - 1));
                        }
                    }
                }
            } else {
                for (int d1 = 0; d1 < divisors[from].size(); ++d1) {
                    graph[vertex[from] + d1].push_back(Edge(end, 1, graph[end].size()));
                    graph[end].push_back(Edge(vertex[from] + d1, 0, graph[vertex[from] + d1].size() - 1));
                }
            }
        }
        n = end;
    }
    void split(int ve, int ev) {
        used[ve] = true;
        if (ev) {
            connect[ve] = ev;
        } else {
            connect[ve] = ev;
        }
        for (int x : graph_base[ve]) {
            if (!used[x]) {
                split(x, ev ^ 1);
            }
        }
    }
    long long solve() {
        long long answer = 0;
        int push = 1;
        int MAX = 0;
        for (int i = 1; i <= n; ++i) {
            for (Edge x : graph[i]) {
                if (x.cap > MAX) {
                    MAX = x.cap;
                }
            }
        }
        while (push <= MAX) {
            push <<= 1;
        }
        push >>= 1;
        while (push) {
            if (!bfs(start, end, push)) {
                push >>= 1;
                continue;
            }
            bool was_update = true;
            ptr.assign(n + 1, 0);
            do {
                int flow_update = dfs(start, end, push, MAX);
                if (!flow_update) {
                    was_update = false;
                }
                answer += flow_update;
            } while (was_update);
        }
        return answer;
    }
    bool dfs_try(int ver) {
        used[ver] = true;
        if (ver == end) {
            return true;
        }
        for (Edge x : graph[ver]) {
            if (!used[x.to] && x.cap) {
                if (dfs_try(x.to)) {
                    return true;
                }
            }
        }
        return false;
    }
};

void solve() {
    Flow solver = Flow();
    solver.init();
    cout << solver.solve() << endl;
}

int main()
{
    //freopen("input", "r", stdin);
    //freopen("output", "w", stdout);
    //  ios_base::sync_with_stdio(false);
    //   cin.tie(NULL);
    solve();
    return 0;
}


#include<iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <fstream>

using namespace std;

typedef vector < vector <int> > graph;

class Flow {
    class Edge {
    public:
        int to, cap, flow, rev_edge;
        Edge() {}
        Edge(int to, int cap, int rev_edge) {
            this->to = to;
            this->cap = cap;
            this->flow = 0;
            this->rev_edge = rev_edge;
        }
    };
public:
    vector < vector < Edge> > graph;
    vector < vector <int> > graph_base;
    vector < vector < int > > divisors;
    vector < int > ptr, dist, used, numbers, vertex, connect;
    int n, m;
    int start, end;
    bool bfs(int start, int end, int min_cap) {
        dist.assign(n + 1, n + 1);
        dist[start] = 0;
        queue <int> q;
        q.push(start);
        while (!q.empty()) {
            int ver = q.front(); q.pop();
            for (Edge x : graph[ver]) {
                if (x.cap < min_cap || x.cap == 0) {
                    continue;
                }
                if (dist[ver] + 1 < dist[x.to]) {
                    dist[x.to] = dist[ver] + 1;
                    q.push(x.to);
                }
            }
        }
        return dist[end] < n + 1;
    }
    int dfs(int ver, int end, int min_cap, int cur_flow) {
        if (ver == end || cur_flow == 0) {
            return cur_flow;
        }
        for (; ptr[ver] < (int)graph[ver].size(); ++ptr[ver]) {
            Edge &x = graph[ver][ptr[ver]];
            if (x.cap < min_cap || dist[ver] + 1 != dist[x.to]) {
                continue;
            }
            int flow_up = dfs(x.to, end, min_cap, min(cur_flow, x.cap));
            if (flow_up == 0) {
                continue;
            } else {
                x.cap -= flow_up;
                graph[x.to][x.rev_edge].cap += flow_up;
                if (x.cap == 0) {
                    ++ptr[ver];
                }
                return flow_up;
            }
        }
        return 0;
    }
    void init2() {
        cin >> n >> m;
        int from, to, cap;
        graph.resize(n + 2);
        for (int i = 0; i < m; ++i) {
            cin >> from >> to >> cap;
            graph[from].push_back(Edge(to, cap, graph[to].size()));
            graph[to].push_back(Edge(from, cap, graph[from].size() - 1));
        }
    }

    void init() {
        unsigned int from, to;
        int cap, tn, tm;
        cin >> tn >> tm;
        divisors.resize(tn);
        vertex.resize(tn);
        numbers.resize(tn);
        connect.resize(tn + 1);
        graph_base.resize(tn + 1);
        for (int i = 0; i < tn; ++i) {
            cin >> numbers[i];
            for (int j = 2; numbers[i] > 1 && j < 32000; ++j) {
                while (numbers[i] % j == 0) {
                    numbers[i] /= j;
                    divisors[i].push_back(j);
                }
            }
            if (numbers[i] > 1) {
                divisors[i].push_back(numbers[i]);
            }
        }
        start = 1;
        vertex[0] = 2;
        for (int i = 1; i < tn; ++i) {
            vertex[i] = vertex[i - 1] + divisors[i - 1].size();
        }
        end = vertex[tn - 1] + divisors[tn - 1].size();
        for (int i = 0; i < tm; ++i) {
            cin >> from >> to;
            graph_base[from].push_back(to);
            graph_base[to].push_back(from);
        }
        used.resize(tn + 1, false);
        for (int i = 1; i <= tn; ++i) {
            if (!used[i]) {
                split(i, 0);
            }
        }
        graph.resize(end + 1);
        for (int i = 1; i <= tn; ++i) {
            from = i - 1;
            if (connect[i]) {
                for (int d1 = 0; d1 < divisors[from].size(); ++d1) {
                    graph[start].push_back(Edge(vertex[from] + d1, 1, graph[vertex[from] + d1].size()));
                    graph[vertex[from] + d1].push_back(Edge(start, 0, graph[start].size() - 1));
                }
                for (int x : graph_base[i]) {
                    to = x - 1;
                    for (int d1 = 0; d1 < divisors[from].size(); ++d1) {
                        for (int d2 = 0; d2 < divisors[to].size(); ++d2) {
                            if (divisors[from][d1] != divisors[to][d2]) {
                                continue;
                            }
                            graph[vertex[from] + d1].push_back(
                                        Edge(vertex[to] + d2, 1, graph[vertex[to] + d2].size()));
                            graph[vertex[to] + d2].push_back(
                                        Edge(vertex[from] + d1, 0, graph[vertex[from] + d1].size() - 1));
                        }
                    }
                }
            } else {
                for (int d1 = 0; d1 < divisors[from].size(); ++d1) {
                    graph[vertex[from] + d1].push_back(Edge(end, 1, graph[end].size()));
                    graph[end].push_back(Edge(vertex[from] + d1, 0, graph[vertex[from] + d1].size() - 1));
                }
            }
        }
        n = end;
    }
    void split(int ve, int ev) {
        used[ve] = true;
        if (ev) {
            connect[ve] = ev;
        } else {
            connect[ve] = ev;
        }
        for (int x : graph_base[ve]) {
            if (!used[x]) {
                split(x, ev ^ 1);
            }
        }
    }
    long long solve() {
        long long answer = 0;
        int push = 1;
        int MAX = 0;
        for (int i = 1; i <= n; ++i) {
            for (Edge x : graph[i]) {
                if (x.cap > MAX) {
                    MAX = x.cap;
                }
            }
        }
        while (push <= MAX) {
            push <<= 1;
        }
        push >>= 1;
        while (push) {
            if (!bfs(start, end, push)) {
                push >>= 1;
                continue;
            }
            bool was_update = true;
            ptr.assign(n + 1, 0);
            do {
                int flow_update = dfs(start, end, push, MAX);
                if (!flow_update) {
                    was_update = false;
                }
                answer += flow_update;
            } while (was_update);
        }
        return answer;
    }
    bool dfs_try(int ver) {
        used[ver] = true;
        if (ver == end) {
            return true;
        }
        for (Edge x : graph[ver]) {
            if (!used[x.to] && x.cap) {
                if (dfs_try(x.to)) {
                    return true;
                }
            }
        }
        return false;
    }
};

void solve() {
    Flow solver = Flow();
    solver.init();
    cout << solver.solve() << endl;
}

int main()
{
    freopen("input", "r", stdin);
    freopen("output", "w", stdout);
    //  ios_base::sync_with_stdio(false);
    //   cin.tie(NULL);
    solve();
    return 0;
}


#include<iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <fstream>

using namespace std;

typedef vector < vector <int> > graph;

class Flow {
    class Edge {
    public:
        int to, cap, flow, rev_edge;
        Edge() {}
        Edge(int to, int cap, int rev_edge) {
            this->to = to;
            this->cap = cap;
            this->flow = 0;
            this->rev_edge = rev_edge;
        }
    };
public:
    vector < vector < Edge> > graph;
    vector < vector <int> > graph_base;
    vector < vector < int > > divisors;
    vector < int > ptr, dist, used, numbers, vertex, connect;
    int n, m;
    int start, end;
    bool bfs(int start, int end, int min_cap) {
        dist.assign(n + 1, n + 1);
        dist[start] = 0;
        queue <int> q;
        q.push(start);
        while (!q.empty()) {
            int ver = q.front(); q.pop();
            for (Edge x : graph[ver]) {
                if (x.cap < min_cap || x.cap == 0) {
                    continue;
                }
                if (dist[ver] + 1 < dist[x.to]) {
                    dist[x.to] = dist[ver] + 1;
                    q.push(x.to);
                }
            }
        }
        return dist[end] < n + 1;
    }
    int dfs(int ver, int end, int min_cap, int cur_flow) {
        if (ver == end || cur_flow == 0) {
            return cur_flow;
        }
        for (; ptr[ver] < (int)graph[ver].size(); ++ptr[ver]) {
            Edge &x = graph[ver][ptr[ver]];
            if (x.cap < min_cap || dist[ver] + 1 != dist[x.to]) {
                continue;
            }
            int flow_up = dfs(x.to, end, min_cap, min(cur_flow, x.cap));
            if (flow_up == 0) {
                continue;
            } else {
                x.cap -= flow_up;
                graph[x.to][x.rev_edge].cap += flow_up;
                if (x.cap == 0) {
                    ++ptr[ver];
                }
                return flow_up;
            }
        }
        return 0;
    }
    void init2() {
        cin >> n >> m;
        int from, to, cap;
        graph.resize(n + 2);
        for (int i = 0; i < m; ++i) {
            cin >> from >> to >> cap;
            graph[from].push_back(Edge(to, cap, graph[to].size()));
            graph[to].push_back(Edge(from, cap, graph[from].size() - 1));
        }
    }

    void init() {
        unsigned int from, to;
        int cap, tn, tm;
        cin >> tn >> tm;
        divisors.resize(tn);
        vertex.resize(tn);
        numbers.resize(tn);
        connect.resize(tn + 1);
        graph_base.resize(tn + 1);
        for (int i = 0; i < tn; ++i) {
            cin >> numbers[i];
            for (int j = 2; numbers[i] > 1 && j < 32000; ++j) {
                while (numbers[i] % j == 0) {
                    numbers[i] /= j;
                    divisors[i].push_back(j);
                }
            }
            if (numbers[i] > 1) {
                divisors[i].push_back(numbers[i]);
            }
        }
        start = 1;
        vertex[0] = 2;
        for (int i = 1; i < tn; ++i) {
            vertex[i] = vertex[i - 1] + divisors[i - 1].size();
        }
        end = vertex[tn - 1] + divisors[tn - 1].size();
        for (int i = 0; i < tm; ++i) {
            cin >> from >> to;
            graph_base[from].push_back(to);
            graph_base[to].push_back(from);
        }
        used.resize(tn + 1, false);
        for (int i = 1; i <= tn; ++i) {
            if (!used[i]) {
                split(i, 0);
            }
        }
        graph.resize(end + 1);
        for (int i = 1; i <= tn; ++i) {
            from = i - 1;
            if (connect[i]) {
                for (int d1 = 0; d1 < divisors[from].size(); ++d1) {
                    graph[start].push_back(Edge(vertex[from] + d1, 1, graph[vertex[from] + d1].size()));
                    graph[vertex[from] + d1].push_back(Edge(start, 0, graph[start].size() - 1));
                }
                for (int x : graph_base[i]) {
                    to = x - 1;
                    for (int d1 = 0; d1 < divisors[from].size(); ++d1) {
                        for (int d2 = 0; d2 < divisors[to].size(); ++d2) {
                            if (divisors[from][d1] != divisors[to][d2]) {
                                continue;
                            }
                            graph[vertex[from] + d1].push_back(
                                        Edge(vertex[to] + d2, 1, graph[vertex[to] + d2].size()));
                            graph[vertex[to] + d2].push_back(
                                        Edge(vertex[from] + d1, 0, graph[vertex[from] + d1].size() - 1));
                        }
                    }
                }
            } else {
                for (int d1 = 0; d1 < divisors[from].size(); ++d1) {
                    graph[vertex[from] + d1].push_back(Edge(end, 1, graph[end].size()));
                    graph[end].push_back(Edge(vertex[from] + d1, 0, graph[vertex[from] + d1].size() - 1));
                }
            }
        }
        n = end;
    }
    void split(int ve, int ev) {
        used[ve] = true;
        if (ev) {
            connect[ve] = ev;
        } else {
            connect[ve] = ev;
        }
        for (int x : graph_base[ve]) {
            if (!used[x]) {
                split(x, ev ^ 1);
            }
        }
    }
    long long solve() {
        long long answer = 0;
        int push = 1;
        int MAX = 0;
        for (int i = 1; i <= n; ++i) {
            for (Edge x : graph[i]) {
                if (x.cap > MAX) {
                    MAX = x.cap;
                }
            }
        }
        while (push <= MAX) {
            push <<= 1;
        }
        push >>= 1;
        while (push) {
            if (!bfs(start, end, push)) {
                push >>= 1;
                continue;
            }
            bool was_update = true;
            ptr.assign(n + 1, 0);
            do {
                int flow_update = dfs(start, end, push, MAX);
                if (!flow_update) {
                    was_update = false;
                }
                answer += flow_update;
            } while (was_update);
        }
        return answer;
    }
    bool dfs_try(int ver) {
        used[ver] = true;
        if (ver == end) {
            return true;
        }
        for (Edge x : graph[ver]) {
            if (!used[x.to] && x.cap) {
                if (dfs_try(x.to)) {
                    return true;
                }
            }
        }
        return false;
    }
};

void solve() {
    Flow solver = Flow();
    solver.init();
    cout << solver.solve() << endl;
}

int main()
{
  //  freopen("input", "r", stdin);
   // freopen("output", "w", stdout);
    //  ios_base::sync_with_stdio(false);
    //   cin.tie(NULL);
    solve();
    return 0;
}