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\n", min (sum_r (), sum_c ())); 127 } 128 129 return 0; 130 }
时间: 2024-10-21 22:28:15