zoukankan      html  css  js  c++  java
  • Codeforces Round #511 (Div. 2) C. Enlarge GCD (质因数)

    题目

    题意:

      给你n个数a[1]...a[n],可以得到这n个数的最大公约数, 现在要求你在n个数中 尽量少删除数,使得被删之后的数组a的最大公约数比原来的大。 如果要删的数小于n,就输出要删的数的个数, 否则输出 -1 。

    思路:

      设原来的最大公约数为 g, 然后a[1]...a[n]都除以g ,得到的新的a[1]...a[n],此时它们的最大公约数一定是1 。

      设除以g之后的数组a为: 

                  1    2    3     6      8   10

       则它们的质因数分别是:  1    2    3    2 3    2    2 5

      其中 质因数 2 的次数出现的最多,出现了4 次, 所以我们只要删除 n-4=2 个数就能使最大公约数由1 变成 2 。即删除 a[1]和a[3]就好,答案就是 2 。

      综上,只要找出质因数出现的最多的次数d, n-d就是我们要的答案。

      代码实现过程中,由于数据较大,要把筛质数 和 选因子  分开来做, 不能同时筛质因子(会超时),因为要避免筛质数这部分重复(打一次表就好)。  筛质数的时候,用2000以内的质数就够了(我也不知道为什么!)

      顺便一提:一个数m 的因子个数k 是小于log2m的 , 因为2^k<m 。 还有 数组至少能开1.5e7 大 。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include <cctype>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cmath>
     7 #include<string>
     8 #include<cmath>
     9 #include<set>
    10 #include<vector>
    11 #include<stack>
    12 #include<queue>
    13 #include<map>
    14 using namespace std;
    15 #define ll long long
    16 #define mem(a,x) memset(a,x,sizeof(a))
    17 #define se second
    18 #define fi first
    19 const ll mod=1e9+7;
    20 const int INF= 0x3f3f3f3f;
    21 const int N=3e5+5;
    22 
    23 
    24 const int N2=1.5e7+5;
    25 int n;
    26 int cnt=0;
    27 int check[2005];
    28 int a[N];
    29 int num[N2];
    30 int prime[N];
    31 
    32 
    33 int gcd(int x, int y)
    34 {
    35     return y==0?x:gcd(y,x%y);
    36 }
    37 void _prime()
    38 {
    39     int m=2000;
    40     for(int i=2;i<=m;i++) //N以内的质数 
    41     {
    42         if(!check[i])
    43         {
    44             prime[++cnt]=i;
    45             for(int j=i;j<=m;j+=i)
    46             {
    47                 check[j]=1;
    48             }
    49         }
    50     }
    51 }
    52 void factor(int m)
    53 {
    54     for(int i=1;i<=cnt;i++)
    55     {
    56         if(m%prime[i]==0)
    57             num[prime[i] ]++;
    58         while(m%prime[i]==0)
    59         {
    60             m/=prime[i];
    61         }
    62     }
    63     if(m!=1) //包括了1 
    64         num[m]++;
    65 }
    66 
    67 int main()
    68 {
    69     cin>>n;
    70     for(int i=1;i<=n;i++)
    71         scanf("%d",&a[i]);
    72     
    73     int g=a[1]; //g=删除前的最大公约数 
    74     for(int i=2;i<=n;i++)    g=gcd(g,a[i]);
    75     
    76     _prime();
    77     for(int i=1;i<=n;i++) 
    78     {
    79         a[i]/=g;
    80         factor(a[i]);
    81     }
    82     
    83     int ans=INF;
    84     for(int i=1;i<=N2;i++)
    85     {
    86         if(num[i])
    87             ans=min(ans,n-num[i]);
    88     }
    89     cout<< (ans<n? ans:-1 )<<endl;
    90 }
    View Code
  • 相关阅读:
    使用MSXML2::IXMLDOMDocument2Ptr每次都要CreateInstance和load(xmlfile)吗?
    .Net程序安装打包的一些经验贡献
    感慨SQL2005中的数据挖掘算法
    COM客户端没法激活托管代码生成的COM Server的原因
    预感~=命中注定
    创业经理10大必备素质
    全局缓存管理工具
    XML DOM的结构概念图解哪里是Element,哪里是Attribute,哪里是Text
    用GetVolumeInformation得到的不是硬盘的序列号,不要再抄这样的错误好吗?
    站在生活的背后
  • 原文地址:https://www.cnblogs.com/thunder-110/p/10122292.html
Copyright © 2011-2022 走看看