【CF 1015(div1+2) B】GCD竟然有奇招

嗨嗨!今天也在补题

做这份怎么连B都做不出来了
明明知道思路就是这样的说
那就看题咯

B. MIN = GCD

You are given a positive integer sequence \(a\) of length \(n\). Determine if it is possible to rearrange \(a\) such that there exists an integer \(i\) (\(1 \le i<n\)) satisfying

描述

给你一个长度为 \(n\) 的正整数序列 \(a\) 。请判断是否有可能重新排列 \(a\) 使得存在一个满足以下条件的整数 \(i\) ( \(1 \le i<n\) ) 满足

\[\min([a_1,a_2,\ldots,a_i])=\gcd([a_{i+1},a_{i+2},\ldots,a_n]). \]

这里 \(\gcd(c)\) 表示 \(c\)最大公约数,它是除以 \(c\) 中所有整数的最大正整数。

输入格式

每个测试包含多个测试用例。第一行包含测试用例的数量 \(t\) ( \(1 \le t \le 10^4\) )。测试用例说明如下。

每个测试用例的第一行都包含一个整数 \(n\) ( \(2 \le n \le 10^5\) )。

第二行包含 \(n\) 个整数 \(a_1, a_2, \ldots, a_n\) ( $1 \le a_i \le 10^{18} $ )。

保证所有测试用例中 \(n\) 的总和不超过 \(10^5\)

输出格式

对于每个测试用例,如果可能,则输出 "是",否则输出 "否"。

可以用任何大小写(大写或小写)输出答案。例如,字符串 "yEs"、"yes"、"Yes "和 "YES "将被识别为肯定回答。

输入

7
2
1 1
2
1 2
3
2 2 3
3
2 3 4
5
4 5 6 9 3
3
998244359987710471 99824435698771045 1000000007
6
1 1 4 5 1 4

输出

Yes
No
Yes
No
Yes
Yes
Yes

解法&&个人感想

考虑数列a中的最小值,不妨设为$ a_p $,则若 $ a_p $放在左侧,右侧必然是 $ a_p $
若 $ a_p $ 放在右侧,则 $ RHS\le a_p $ ,同时 $ LHS \ge a_p $,得出 $ RHS = LHS =a_p $
此时,我们对整个数列 $ {a_n} $进行考量,我原来的思路是如果 $ n \ge 2 $时,其中有与 $ a_p $ 相同的数,或者有两个 $ a_p $的倍数,就成立
这个思路本身没错,但是我漏了一个关键点,就是任何数都是1的倍数,这个就比较抽象,导致卡了很久都没出来
现在,我们来看答案的解法:
答案先取出最小值,然后遍历所有能被 $ a_p $整除的数,对它们取最大公约数,最后验证是否与 $ a_p $ 相等
那么,它的正确性?
不妨假设 $ a_p =1 $ ,对其他所有数遍历,如果其最大公因数是1,那么分类必然可行,如果不是的话,由于取部分数的最大公约数必然大于等于整体的最大公约数,所以矛盾了
如果 $ a_p $ 不是1的话,自然,不被 $ a_p $ 整除的数必然会放在左边,而右边只剩下能被 $ a_p $整除的数,还是由于部分数的最大公约数必然大于等于整体的最大公约数,所以右边的最大公约数只有等于 $ a_p $ 才成立
下面看代码(答案用vector,我没那么熟练直接开数组了)

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
int t,n;
ll a[200005];
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        ll mi=2e18;
        int k=0;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            if(a[i]<mi){
                mi=a[i];
                k=i;
            }
        }
        ll g=0;
        for(int i=1;i<=n;i++){
            if(i!=k&&a[i]%a[k]==0){
                g=__gcd(g,a[i]);
            }
        }
        if(g==a[k]) printf("YES\n");
        else printf("NO\n");
    }
    system("pause");
    return 0;
}

这种题目还得多练锻炼思维的说
好了,我们放一张刀子,痛,太痛了,可没办法,谁叫我就感同身受好这口呢
alt text

P.S 最近补题收获还是很大

posted @ 2025-04-19 11:04  elainafan  阅读(10)  评论(0)    收藏  举报