虽然是 A 题,也简单写个证明:
由题意,m   m o d   a = m   m o d   b m \bmod a = m \bmod b m m o d a = m m o d b m = t a + r = k b + r m = ta + r = kb + r m = t a + r = k b + r t a = k b ta = kb t a = k b t , k , r t,k,r t , k , r r = 0 r = 0 r = 0 gcd  ( a , b ) = d ,   a = a 0 d ,   b = b 0 d \gcd(a,b) = d,\ a = a_{0}d,\ b = b_{0}d g cd( a , b ) = d ,   a = a 0  d ,   b = b 0  d t a 0 = k b 0 ta_{0} = kb_{0} t a 0  = k b 0  a 0 , b 0 a_{0},b_{0} a 0  , b 0  t = b 0 t = b_{0} t = b 0  m = t a = b 0 a = lcm  ( a , b ) m = ta = b_{0}a = \operatorname{lcm}(a, b) m = t a = b 0  a = l c m ( 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 ; } 
贪心。时间复杂度Θ ( n ) \Theta(n) Θ ( 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 找到所有能出去的点,没有搜到的就是会被困住的(因为出现环搜不到,若干个 ? 相连也搜不到)。最后扫一遍如果某个 ? 点的周围四个点都是能出去的,那这个点也不可能被困住。
时间复杂度Θ ( m n ) \Theta(mn) Θ ( m 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 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 存位置,时间复杂度Θ ( n log  n ) \Theta(n\log n) Θ ( 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 ∣ n ( n + 1 ) 2 k n\mid \frac{n(n+1)}{2}k n ∣ 2 n ( n + 1 )  k n n n k k k k = 1 k = 1 k = 1 n = 1 n = 1 n = 1 
k = 3 k = 3 k = 3 
1 2 3 4 5 5 2 4 1 3 3 5 2 4 1 \begin{array}{ccccc} 1 & 2 & 3 & 4 & 5 \\ {\color{red}5} & 2 & {\color{blue}4} & 1 & {\color{green}3} \\ {\color{green}3} & {\color{red}5} & 2 & {\color{blue}4} & 1 \end{array} 1 5 3  2 2 5  3 4 2  4 1 4  5 3 1  
这样如果k k k k k k 
剩下的就全排列轮换,相邻两行相加为n + 1 n + 1 n + 1 
如果全排列轮换之后总数能达到k k k k = n ! − 1 k = n! - 1 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 ; }