虽然是 A 题,也简单写个证明:
由题意,$m \bmod a = m \bmod b$,设 $m = ta + r = kb + r$,则 $ta = kb$。希望 $t,k,r$ 尽可能小,则 $r = 0$。再设 $\gcd(a,b) = d,\ a = a{0}d,\ b = b {0}d$,则 $ta{0} = kb {0}$,由于 $a{0},b {0}$ 互素,只能取 $t = b{0}$,此时 $m = ta = b {0}a = \operatorname{lcm}(a, b)$。
不要按题意暴力,会 TLE。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <bits/stdc++.h> using namespace std;int main () { int t; cin >> t; while (t--) { int a, b; cin >> a >> b; cout << lcm (a, b) << endl; } return 0 ; }
贪心。时间复杂度 $\Theta(n)$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <bits/stdc++.h> using namespace std;int main () { int t; cin >> t; while (t--) { int n, m, k; cin >> n >> m >> k; string s; cin >> s; int cnt = 0 , ans = 0 , r = 0 ; for (int i = 0 ; i < n; i++) { if (i >= r && s[i] == '0' ) { s[i] = '1' ; if (++cnt == m) { ans++; cnt = 0 ; r = i + k; } } else { cnt = 0 ; } } cout << ans << "\n" ; } return 0 ; }
CF 似乎没考过这种题……
连反边,从最外层 BFS/DFS 找到所有能出去的点,没有搜到的就是会被困住的(因为出现环搜不到,若干个 ?
相连也搜不到)。最后扫一遍如果某个 ?
点的周围四个点都是能出去的,那这个点也不可能被困住。
时间复杂度 $\Theta(mn)$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 #include <bits/stdc++.h> using namespace std;using ll = long long ;int main () { int t; cin >> t; while (t--) { int n, m; cin >> n >> m; auto change = [&](int x, int y) { return x * (m + 1 ) + y; }; auto get = [&](int x) { return pair (x / (m + 1 ), x % (m + 1 )); }; vector<vector<int >> E ((n + 2 ) * (m + 2 )); vector<int > deg ((n + 2 ) * (m + 2 )) ; vector<int > res ((n + 2 ) * (m + 2 )) ; vector<string> s (n + 2 ) ; for (int i = 1 ; i <= n; i++) { for (int j = 1 ; j <= m; j++) { char c; cin >> c; int u = change (i, j), v; res[u] = 1 ; if (c == '?' ) continue ; else if (c == 'U' ) v = change (i - 1 , j); else if (c == 'D' ) v = change (i + 1 , j); else if (c == 'L' ) v = change (i, j - 1 ); else if (c == 'R' ) v = change (i, j + 1 ); E[v].push_back (u); deg[u]++; } } queue<int > Q; for (int i = 1 ; i <= n; i++) { Q.push (change (i, 0 )); Q.push (change (i, m + 1 )); } for (int j = 1 ; j <= m; j++) { Q.push (change (0 , j)); Q.push (change (n + 1 , j)); } while (!Q.empty ()) { int u = Q.front (); Q.pop (); for (auto v : E[u]) { res[v] &= res[u]; if (--deg[v] == 0 ) { Q.push (v); } } } int ans = 0 ; for (int i = 1 ; i <= n; i++) { for (int j = 1 ; j <= m; j++) { int u = change (i, j); bool flag = 1 ; for (int v : { change (i - 1 , j), change (i + 1 , j), change (i, j - 1 ), change (i, j + 1 ) }) { if (res[v] == 1 ) { flag = 0 ; break ; } } if (flag) { res[u] = 0 ; } ans += res[u]; } } cout << ans << '\n' ; } return 0 ; }
做法:
选取最左边的 1
和最右边的 0
,或者最左边的 2
和最右边的 1
交换(先选谁没有影响),如此反复直至找不到。 合理性:
用 set
存位置,时间复杂度 $\Theta(n\log n)$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <bits/stdc++.h> using namespace std;using ll = long long ;int main () { int t; cin >> t; while (t--) { int n; cin >> n; array<set<int >, 3> s; for (int i = 0 ; i < n; i++) { int x; cin >> x; s[x].insert (i); } s[2 ].insert (n); s[0 ].insert (-1 ); vector<array<int , 2>> res; for (int op = 0 ; ; op ^= 1 ) { int u = *s[1 ].begin (); int v = *s[0 ].rbegin (); if (u < v) { res.push_back ({ u, v }); s[1 ].erase (s[1 ].begin ()); s[0 ].erase (prev (s[0 ].end ())); s[0 ].insert (u); s[1 ].insert (v); continue ; } else { u = *s[2 ].begin (); v = *s[1 ].rbegin (); if (u < v) { res.push_back ({ u, v }); s[2 ].erase (s[2 ].begin ()); s[1 ].erase (prev (s[1 ].end ())); s[1 ].insert (u); s[2 ].insert (v); } else { break ; } } } cout << int (res.size ()) << '\n' ; assert (int (res.size ()) <= n); for (auto & [l, r] : res) { cout << l + 1 << ' ' << r + 1 << '\n' ; } } return 0 ; }
构造,不好评价。
由于 $n\mid \frac{n(n+1)}{2}k$,因此如果 $n$ 是偶数,$k$ 是奇数就无解。$k = 1$ 除了 $n = 1$ 都无解。下面考虑剩下的情况:
$k = 3$ 是有解的,例如
这样如果 $k$ 是奇数,就先构造三行让 $k$ 变成偶数。
剩下的就全排列轮换,相邻两行相加为 $n + 1$,如果轮换到了刚才构造的三行需要跳过。
如果全排列轮换之后总数能达到 $k$ 就有解,否则无解(事实上这种情况下只有 $k = n! - 1$ 无解)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 #include <bits/stdc++.h> using namespace std;using ll = long long ;const ll inf = 1e15 ;int main () { int t; cin >> t; while (t--) { int n, k; cin >> n >> k; ll fac = 1 ; for (int i = 1 ; i <= n && fac < inf; i++) { fac *= i; } if (n % 2 == 0 && k % 2 == 1 || k > fac) { cout << "NO" << endl; } else if (k == 1 ) { if (n == 1 ) { cout << "YES" << endl; cout << 1 << endl; } else { cout << "NO" << endl; } } else { vector<vector<int >> res; vector b (3 , vector<int >(n + 1 )) ; if (k % 2 == 1 ) { for (int i = 1 ; i <= n; i++) { b[0 ][i] = i; b[1 ][i] = (i & 1 ? (n + (1 - i) / 2 ) : ((n + 1 ) / 2 - i / 2 )); b[2 ][i] = (i & 1 ? ((n + 1 ) / 2 - i / 2 ) : (n + (1 - i) / 2 )); } for (int i = 0 ; i < 3 ; i++) { res.push_back (b[i]); } k -= 3 ; } vector<int > p (n + 1 ) ; iota (p.begin (), p.end (), 0 ); for (int t = 0 ; t < fac / 2 && k; t++) { vector a (2 , vector<int >(n + 1 )) ; for (int i = 1 ; i <= n; i++) { a[0 ][i] = p[i]; a[1 ][i] = n + 1 - p[i]; } bool good = true ; for (int j = 0 ; j < 2 ; j++) { for (int k = 0 ; k < 3 ; k++) { if (b[k] == a[j]) { good = false ; break ; } } } if (good) { for (int j = 0 ; j < 2 ; j++) { res.push_back (a[j]); } k -= 2 ; } next_permutation (p.begin () + 1 , p.end ()); } if (k) { cout << "NO" << endl; } else { cout << "YES" << endl; for (int i = 0 ; i < res.size (); i++) { for (int j = 1 ; j <= n; j++) { cout << res[i][j] << " " ; } cout << endl; } } } } return 0 ; }