1006.GCD Game
题目大意:
给定 n 个数字。他们轮流操作,每次进行以下操作。
- 任意选择其中一个数字 a i a_i ai。
- 任意找一个 x ( 1 ≤ x < a i ) x(1≤x<a_i) x(1≤x<ai)
- 将数字 a i a_i ai替换为 g c d ( a i , x ) g c d ( a_i , x ) gcd(ai,x)
思路:
筛选质因子个数,然后Nim博弈。
先打个线性的表。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e7 + 1000;
bool is_prime[maxn];
ll prime[maxn], cnt = 0, fac[maxn];
void euler(int p)
{
is_prime[0] = is_prime[1] = 1;
for (ll i = 2; i <= p; ++i)
{
if (!is_prime[i])
prime[++cnt] = i, fac[i] = 1;
for (ll j = 1; j <= cnt && i * prime[j] <= p; ++j)
{
is_prime[i * prime[j]] = true;
fac[i * prime[j]] = 1 + fac[i];
if (i % prime[j] == 0)
break;
}
}
}
int main()
{
euler(maxn - 100);
int t;
scanf("%d", &t);
while (t--)
{
int n;
scanf("%d", &n);
ll sg = 0;
for (int i = 1; i <= n; i++)
{
int x;
scanf("%d",&x);
sg ^= fac[x];
}
if (sg)
printf("Alice\n");
else
printf("Bob\n");
}
}
Nim博弈:
Nim博弈:
题意:
有N堆石子。A B两个人轮流拿,A先拿。每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜。
分析:
当(0,0,0)时,为必败局。
当(0,0,1)时,为必胜局 。
当(0,0,2)时,为必胜局 。
…
所以,将所有的石子进行异或操作,当异或值为 0时 ,后者必胜 ,否者,前者必胜。