牛客多校 A 题题解

牛客多校 8 - A

Haitang and Game

Given a set S, dXqwq and Haitang take turns performing the following operations, with dXqwq going first:

  • Find a pair (x,y) such that x,yS and gcd(x,y)S.

  • Insert gcd(x,y) into S.

The player who cannot make a move loses the game. You need to output the winner when both players play optimally.

Each test contains multiple test cases. The first line contains an integer T (1T20) — the number of test cases. The description of the test cases follows.

The first line of each test case contains a single integer n (1n105) — the size of set S.

The second line contains n integers a1,a2,,an (1a1<a2<<an105) — the elements of set S.

解题思路:

考场上这题没优化好导致 95.46 的样例通过,而最后 4.54 的样例被卡了,我真的服了
95分被卡

  • 简单分析之后可以发现,无论两边最后怎么选,最后的形成的数列的个数是固定的,如果最后形成的数列的个数比原本的数列的个数增加奇数个,那么 dXqwq 胜利, 否则 Haitang 胜利.
  • 而要怎么找出所有的可能插入的 gcd 呢? 首先,观察到数据范围在 1a105 的范围,我们可以开一个 bool类型的哈希表来记录在初始的集合中出现过的元素,然后我们枚举可能还可以在插入的数据 i (1i5×104 ) ,在枚举过程中,如果已经在集合中就直接跳过,如果不在集合中,就需要开始判断,判断的过程中,遍历 在 1x1×105i 的倍数,这里注意,我考场上把每两个 i 的倍数都进行了 gcd运算, 这样直接导致我考场上这一题 TLE 了几十发...... 实际上,只需要把所有的 i 的倍数的数一起求最大公因数,如果最大公倍数为 i 那么说明 i 最后需要被插入到集合 S 中.这里开始证明: 如果存在 k1ik2i 的最大公因数为 i ,就可以得出 gcd(k1,k2)=1 , k1k2 互质,gcd(k1,k2,......kn1,kn)=1 ,那么 . 下证必要性, 若存在 gcd(k1i,k2i,......kn1i,kni)=i ,即 gcd(k1,k2,......kn1,kn)=1 ,我们如何证明存在 gcd(ki,kj)=1 呢? 该出采用反证法,如果 任意 kikj 都两两不互质,则 存在 公因数 t (t1)可以被提出来最后必然存在 gcd(k1,k2,k3,......kn1,kn)1 ,与结论相悖 ,故可以得出, 若所有的i 的倍数的元素的公因数是 i ,那么必然存在最少一对 i 的倍数的元素的公因数是 i ,若在 i 的倍数的元素中存在两个数的公因数是 i ,那么必然存在所有的 i的倍数的元素的公因数 i ,也就是为 i ,所以综上只需要求一下所有的 i 的倍数的元素的最大公因数并判断是否为 i 即可得出是否存在两个元素的gcd(ai,aj)是否为 i.
  • 总结: 对基本的数论知识不熟。

AC code:

#include <bits/stdc++.h>
#define print(x)    cout<<#x<<'='<<x<<'\n'
using namespace std;
const int maxn = 1e5 + 9;
int a[maxn];
int read()
{
    int x = 0, f = 1;
    char c = getchar();
    while (!isdigit(c))
    {
        if (c == '-')
            f = -1;
        c = getchar();
    }
    while (isdigit(c))
    {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x * f;
}
int n;
int gcd(int x, int y)
{
    return y == 0 ? x : gcd(y, x % y);
}
int ct=0;
void solve()
{
    auto Y = [&]()
    {
        cout << "dXqwq" << "\n";
    };
    auto N = [&]()
    {
        cout << "Haitang" << '\n';
    };
    cin >> n;
    vector<bool> mm(1e5 + 9, 0);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        mm[a[i]] = 1;
    }
    int count = 0;
    for (int _ = 50000; _ >= 1; _--)
    {
        // print(_);   
        if (!mm[_])
        {
            int t=0;
            for (int i = 2*_; i <= 100000; i+=_)
            {
                if (mm[i])
                {   
                    t=__gcd(t,i);
                }
            }
            if(t==_)
            {
                mm[_]=1;
                count++;
            }
        }
    }
    if(count&1)
    {
        Y();
    }
    else N();
    // print(++ct);
}
int main()
{
    std::ios::sync_with_stdio(0);
    std::cin.tie(0),cout.tie(0);
//     freopen("1data.in","r",stdin);
    int t;
//     int st = clock();
    cin >> t;
    while (t--)
        solve();
//     int ed = clock();
//     cerr << ed - st;
    return 0;
}
posted @   -风间琉璃-  阅读(59)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示