zoukankan      html  css  js  c++  java
  • Orac and LCM

    题面

    题目链接

    https://codeforces.com/contest/1349/problem/A

    题目大意

    给你一个长度为 N 的数组,求 gcd {lcm({ai , aj}) | i < j} 

    解题思路

    这道题有两种解法

    ① :

    对于 a1 , 产生的 lcm 为 lcm(a1 , a2) , lcm(a1 , a3) ... lcm(a1 , an)

    产生的 gcd_1 为 gcd ( lcm(a1 , a2) , lcm(a1 , a3) ... lcm(a1 , an) ) 

    因为参与 gcd_1 的每一项都是 a1 的倍数

    所以 gcd( lcm(a1 , a2) , lcm(a1 , a3) ... lcm(a1 , an) ) 可以化为 lcm (a1 , gcd (a2 , a3 , ... an) )

    那么最后答案就为 ans = gcd( gcd_1 , gcd_2 , ... gcd_n )  , 我们维护一个后缀就可以搞定了

    ② : 

    假设 ai 没有 2 这个因子,且 aj 也没 2 这个因子,那么 lcm(a[i] , a[j]) 就不包含 2 这个因子

    那么 ans = gcd {lcm({ai , aj}) | i < j} 也就不包含 2 这个因子 

    也就是说数组中如果有两个以上的数都不包含某个因子,那么答案也就不包含这个因子

    所以我们可以对每个质因子开个容器,然后对每个数进行质因子分解

    并将分解后质因子的幂次存于对应质因子的容器中

    然后计算答案时判断每个质因子的容器大小是否大于等于 N - 1

    如果是则说明数组中少于两个数没有这个质因子,则答案必定要乘上这个质因子

    至于是该乘上这个质因子的几次方,我们对容器升序排个序

    如果容器的大小等于 N 则取第二个元素次小幂次,如果等于 N - 1则取第一个元素最小幂次

    以某质数容器的大小为 N 举例 :

    最后一个元素对应最大幂次,只有一个数包含了这个它,倒数第二个元素对应次大幂次,有两个数包含了它

    以此类推第二个元素对应次小幂次,有 N - 1 个数包含了它,第一个元素为最小次幂,有 N 个数包含了它

    因为只需要 N - 1个数有包含它答案就可以乘上它,所以我们选第二个元素作为幂次

    (这里次小不是严格意义上的次小,即 最小 <= 次小)

    AC_Code ①

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N = 3e5 + 10;
    int gcd(int a , int b)
    {
        return b ? gcd(b , a % b) : a;
    }
    int lcm(int a , int b)
    {
        return a * b / gcd(a , b);
    }
    int a[N] , suf[N];
    signed main()
    {
        ios::sync_with_stdio(false); 
        int n , ans = 0;
        cin >> n; 
        for(int i = 1 ; i <= n ; i ++) cin >> a[i];
        for(int i = n ; i >= 1 ; i --) suf[i] = gcd(suf[i + 1] , a[i]);
        for(int i = 1 ; i <= n ; i ++) ans = gcd(ans , lcm(a[i] , suf[i + 1]));
        cout << ans << '
    ' ; 
        return 0;
    }

    AC_Code ②

    #include<bits/stdc++.h>
    #define int long long 
    using namespace std;
    const int N = 2e5 + 10;
    int prime[N] , minprime[N];
    vector<int>vec[N];
    int pow_mod(int x , int n)
    {
        int res = 1;
        while(n)
        {
            if(n & 1) res = res * x;
            x = x * x; 
            n >>= 1;
        }
        return res;
    }
    int euler(int n)
    {
        int c = 0 , i , j;
        for(int i = 2 ; i <= n ; i ++ )
        {
            if(!minprime[i]) prime[++ c] = i , minprime[i] = i;
            for(j = 1 ; j <= c && i * prime[j] <= n ; j++)
            {
                minprime[i * prime[j]] = prime[j];
                if(i % prime[j] == 0) break;
            }
        }
        return c;
    }
    void get_prime(int n)
    {
        for(int i = 1 ; i <= n ; i ++)
        {
            int x = prime[i]; 
            if(x * x > n) break ; 
            if(n % x == 0)
            {
                int c = 0;
                while(n % x == 0) n /= x , c ++ ; 
                vec[x].push_back(c);
            }
        }
        if(n > 1) vec[n].push_back(1);
    }
    signed main()
    {
        ios::sync_with_stdio(false);
        int cnt = euler(N - 10);
        int n , x , ans = 1;
         cin >> n;
         for(int i = 1 ; i <= n ; i ++)
         {
             cin >> x; 
             get_prime(x);
        }
        for(int i = 1 ; i <= cnt ; i ++)
        {
            int x = prime[i];
            sort(vec[x].begin() , vec[x].end());
            if(vec[x].size() == n) ans *= pow_mod(x , vec[x][1]);
            else if(vec[x].size() == n - 1) ans *= pow_mod(x , vec[x][0]);
        }
        cout << ans << '
    ' ; 
        return 0;
    }
    凡所不能将我击倒的,都将使我更加强大
  • 相关阅读:
    两个错误的解决方案
    利用BeautifulSoup爬去我爱我家的租房数据
    使用Docker安装PaddlePaddle安装过程中出现的几个问题
    将博客搬至CSDN
    iOS---实现在屏幕上实时绘图的简单效果---CAShaperLayer和UIBezierPath的简单运用
    举例理解Hibernate的三种状态(转)
    关于hibernate5的映射文件和配置文件改变(转)
    数据库事务四种隔离级别
    使用idea构建Hibernate5项目
    手把手教你如何把java代码,打包成jar文件以及转换为exe可执行文件
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/12880236.html
Copyright © 2011-2022 走看看