题目传送门
1 /*
2 二分查找/暴力:先埃氏筛选预处理,然后暴力对于每一行每一列的不是素数的二分查找最近的素数,更新最小值
3 */
4 #include <cstdio>
5 #include <cstring>
6 #include <algorithm>
7 using namespace std;
8
9 const int MAXN = 5e2 + 10;
10 const int MAXM = 1e6 + 10;
11 const int INF = 0x3f3f3f3f;
12 int a[MAXN][MAXN];
13 int mn_r[MAXN];
14 int mn_c[MAXN];
15 bool is_prime[MAXM];
16 int prime[MAXM];
17 int n, m, x, y;
18 int tot;
19
20 void solve(void)
21 {
22 for (int i=1; i<=1e6; ++i) is_prime[i] = true;
23 is_prime[1] = false;
24 for (int i=2; i<=1e6; ++i)
25 {
26 if (is_prime[i])
27 {
28 prime[++tot] = i;
29 for (int j=i*2; j<=1e6; j+=i) is_prime[j] = false;
30 }
31 }
32 }
33
34 bool check_r(void)
35 {
36 memset (mn_r, 0, sizeof (mn_r));
37 bool ok = true;
38 for (int i=1; i<=n; ++i)
39 {
40 for (int j=1; j<=m; ++j)
41 {
42 if (!is_prime[a[i][j]])
43 {
44 ok = false; mn_r[j]++;
45 }
46 }
47 }
48
49 return ok;
50 }
51
52 bool check_c(void)
53 {
54 memset (mn_c, 0, sizeof (mn_c));
55 bool ok = true;
56 for (int j=1; j<=m; ++j)
57 {
58 for (int i=1; i<=n; ++i)
59 {
60 if (!is_prime[a[i][j]])
61 {
62 ok = false; mn_c[j]++;
63 }
64 }
65 }
66
67 return ok;
68 }
69
70 int sum_r(void)
71 {
72 int ans = INF; int tmp = 0;
73 for (int i=1; i<=n; ++i)
74 {
75 tmp = 0; bool ok = true;
76 for (int j=1; j<=m; ++j)
77 {
78 if (!is_prime[a[i][j]])
79 {
80 int p = lower_bound (prime+1, prime+1+tot, a[i][j]) - prime;
81 if (p <= tot) tmp += prime[p] - a[i][j];
82 else {ok = false; break;}
83 }
84 }
85 if (ok) ans = min (ans, tmp);
86 }
87
88 return ans;
89 }
90
91 int sum_c(void)
92 {
93 int ans = INF; int tmp = 0;
94 for (int j=1; j<=m; ++j)
95 {
96 tmp = 0; bool ok = true;
97 for (int i=1; i<=n; ++i)
98 {
99 if (!is_prime[a[i][j]])
100 {
101 int p = lower_bound (prime+1, prime+1+tot, a[i][j]) - prime;
102 if (p <= tot) tmp += prime[p] - a[i][j];
103 else {ok = false; break;}
104 }
105 }
106 if (ok) ans = min (ans, tmp);
107 }
108
109 return ans;
110 }
111
112 int main(void) //Codeforces Round #166 (Div. 2) B. Prime Matrix
113 {
114 // freopen ("B.in", "r", stdin);
115
116 solve ();
117 while (scanf ("%d%d", &n, &m) == 2)
118 {
119 for (int i=1; i<=n; ++i)
120 {
121 for (int j=1; j<=m; ++j)
122 scanf ("%d", &a[i][j]);
123 }
124
125 if (check_r () || check_c ()) {puts ("0"); continue;}
126 else printf ("%d
", min (sum_r (), sum_c ()));
127 }
128
129 return 0;
130 }