• 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
  • 相关阅读:
    CAS单点登录(一)——初识SSO
    Sql Server 增加字段、修改字段、修改类型、修改默认值
    SQL 聚合函数-非聚合函数
    漫画:什么是中台?
    windows下nginx的安装及使用
    sql优化点
    如何处理sql中的关键字(例如',%)
    Mysql 如何创建一张临时表
    MySQL中information_schema是什么
    mysql查看表结构命令,如下:
  • 原文地址:https://www.cnblogs.com/thunder-110/p/10122292.html
Copyright © 2020-2023  润新知