• AtCoder Beginner Contest 191 F


    链接

    题意:

    给定一个数组,每次从数组中拿两个数A 、B出来,再放一个数C进去,且C = min(A , B) 或者 C = gcd(A , B),问剩下的最后一个数有多少种可能。

    思路:

    假设数组为 a[ ]

    首先,如果对所有的数取min的话,那么留下来的一定是最小的那个。

    其次,对于一个式子 C = GCD(A , B) , 那么一定满足:C <= A && C <= B

    于是,无论剩下的最后一个数是多少 (假设他是ans),一定有 ans <= min(a[1],a[2]...a[n]) 

    条件①:ans <= min(a[1],a[2]...a[n]) 

    接着我们可以发现,ans 一定是 a[i]的因子,因为gcd(A,B)本身就是在寻找A、B中最大相同因子

    条件②:ans 是a[i]的因子

    所以我们就对a[i]的因子进行筛选,什么样的因子可以作为答案?

    样例1:

    可以发现 1 这个因子,其实是三个数中共有的因子,为什么它不作为答案的一部分?(答案是3和6)

    换句话说,1这个因子太小了,小到无论用min或者gcd,都到达不了它,那我们就筛出可以到达的因子。

    换句话说,对于一个因子T 假如有一部分的数,可以通过gcd或者min的操作得到因子T,那么这个因子T就对答案的贡献+1。

    并且,gcd其实比min更容易得到更小的数(这个好理解)

    所以对于一个因子T,把所有包含这个因子的a[i]集合进行GCD操作,即如果a[1],a[2],a[3]为数组中所有包含因子T的数,那么我取minn = gcd(a[1],a[2],a[3])

    此时的minn是我能通过gcd(与min操作)这些数的最小的数了,如果minn <= T (其实这里我没有太想好应该写等号还是小于等于,因为minn=gcd(所有包含因子T的数),思考有没有可能minn小于T,但是gcd(部分包含因子T的数) = T ) , 那么cnt ++

     

    于是我写的是:

      先找出a[i]的所有小于min(a[1],a[2]...a[n]) 因子,然后判断所有包含这个因子的数的gcd是否小于这个因子,是就++

    参考此处

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define ll long long
    #define pb push_back
    #define debug(a) cout << #a << ' ' << a << '
    ';
    #define debug2(a , b) cout << #a << ' ' << a << " || " << #b << ' ' << b << '
    ';
    #define ye cout << "YES
    ";
    #define no cout << "NO
    ";
    const int maxn = 1e6 + 10;
    const int mod = 1e9 + 7;
    using namespace std;
    int a[maxn];
    map<int , int>ma;
    int cnt = 0; 
    int re[maxn];
    signed main() 
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
    
        int n ;
        cin >> n;
        int minn = 1e18;
        for(int i = 1 ; i <= n ; i ++) cin >> a[i] , minn = min(minn , a[i]);
        for(int i = 1 ; i <= n ; i ++){
            for(int j = 1 ; j * j <= a[i] ; j ++){
                if(a[i] % j == 0){
                    if(ma[j] == 0){
                        ma[j] = ++ cnt;
                    }
                    re[ma[j]] = __gcd(re[ma[j]] , a[i]);
                    if(a[i] / j != j){
                        int now = a[i] / j;
                        if(ma[now] == 0){
                            ma[now] = ++ cnt;
                        }
                        re[ma[now]] = __gcd(re[ma[now]] , a[i]);
                    }
                } 
            }
        }
        int ans = 0;
        for(auto i : ma){
            if(re[i.second] <= minn && re[i.second] <= i.first){
                ans ++;
            //    debug2(i.first , re[i.second])
            } 
        }
        cout << ans << '
    ';
        return 0;
    }
    
    /*
    6
    2 2 1 3 2 2
    */
    View Code
  • 相关阅读:
    redis 写入数据 越来越慢 是什么原因
    redis slowlog
    JavaCC 规格严格
    Lucene 规格严格
    数据库建立索引要点 规格严格
    编辑距离 规格严格
    Lucene NRT (Near Real Time) 规格严格
    事件关联 规格严格
    linux下mysql5.5.19编译安装笔记【已验证】 规格严格
    关于CLOSE BY CLIENT STACK TRACE 规格严格
  • 原文地址:https://www.cnblogs.com/GoodVv/p/14394868.html
Copyright © 2020-2023  润新知