AT_agc010_d [AGC010D] Decrementing

lalaouye發表於2024-11-24

有跡可循的思維題,切完之後感覺很爽!

考慮慢慢想一些性質:

  1. 可以注意到只會除以 \(\log\)\(\gcd\)
  2. 只要存在了一個數字 \(1\),那麼之後勝負只與奇偶性有關。對於一名玩家儘可能要在達到存在一個 \(1\) 之前調整好奇偶性。
  3. 發現大多數操作也改變不了奇偶性,只有所有數字都為偶數之後除一次才有奇偶性變化。
  4. 想除一次 \(\gcd\) 是很困難的,而阻止對方除一次 \(\gcd\) 是簡單的。

那麼現在如果當前玩家急需調整一次奇偶性,只有可能在最開始只存在一個奇數的時候做除法。因為對方肯定不希望你調整。不難發現如果先手處於奇偶性的優勢則先手必勝,因為先手可以保證後手永遠無法調整奇偶性。而先手如要調整則會不斷調整,直到當前先手處於奇偶性優勢或者存在不止兩個奇數為止,而頂多只會進行 \(\log\) 次除法,那麼我們就用優美的做法完成了一道優美的題。

程式碼:

#include <bits/stdc++.h>
#define int long long
#define ls (p << 1)
#define rs (ls | 1)
#define rep(i, l, r) for (int i = l; i <= r; ++ i)
#define rrp(i, l, r) for (int i = r; i >= l; -- i)
#define pii pair <int, int>
#define eb emplace_back
#define x first
#define y second
#define inf 1000000000
#define linf 1000000000000000000
using namespace std;
typedef long long ll;
constexpr int N = 1e5 + 5, P = 998244353;
inline int rd () {
	int x = 0, f = 1;
	char ch = getchar ();
	while (! isdigit (ch)) { if (ch == '-') f = -1; ch = getchar (); }
	while (isdigit (ch)) { x = (x << 1) + (x << 3) + ch - 48; ch = getchar (); }
	return x * f;
}
int n, a[N];
int32_t main () {
  // freopen ("1.in", "r", stdin);
  // freopen ("1.out", "w", stdout);
  n = rd ();
  int s = 0;
  rep (i, 1, n) {
    a[i] = rd ();
    s ^= a[i] & 1;
  }
  if (s ^ (n & 1)) {
    puts ("First");
  } else {
    bool win = 0, now = 0;
    while (1) {
      if (win ^ now) {
        break;
      }
      rep (i, 1, n) if (a[i] > 1 && (a[i] & 1)) {
        -- a[i]; break;
      }
      int g = 0, sum = 0;
      rep (i, 1, n) g = __gcd (g, a[i]), sum += a[i];
      if (g == 1) break; sum /= g;
      rep (i, 1, n) a[i] /= g;
      if ((sum & 1) == (n & 1)) win ^= 1; now ^= 1;
    }
    puts (win ? "First" : "Second");
  }
}

相關文章