zoukankan      html  css  js  c++  java
  • CF1047C-Enlarge GCD-(欧拉筛+gcd+唯一分解定理)

    https://vjudge.net/problem/CodeForces-1047C

    说明:第一次记录的时候代码是超时的,本校校内赛出题人改编的,数据被缩小了,没有再cf上ac就贴了,很抱歉。另外,也不需要map这个东西,因为我做的校内赛的题a[i]被改成1e8,数组放不下所以需要map,而原题的数据是够范围的。修正时间:2019.7.27.14:26

    题意:有n个数,他们有个最大公约数设为maxxgcd,要删去最少个数,使得剩下的数的gcd大于maxxgcd。

    解题:先求出原来的数的最大gcd,每个数除以maxxgcd,之后所有数的gcd为1。用分解质因数,最多数拥有的质因子便是新的gcd,大于1就行,除掉那些不含该质因子的数。

    比如有5个数6 4 8 16 32最大公约数为2

    除以2后变成3 2 4 8 16,除以原本的maxxgcd=2之后,大家都有2这个质因数,唯独3没有,则3的引入全部的公约数中必然会导致公约数变小,3 2 4 8 16的最大公约数则是1,如果不要3,2 4 8 16的最大公约数是2.

    返回到原始数组,删掉6之后,4 8 16 32的最大公约数就是4了,比原来的2大。

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<math.h>
    #include<map>
    #include<string>
    #define ll long long
    #define inf 0x3f3f3f3f
    using namespace std;
    
    int n;
    int prime[10086];
    bool vis[10086];
    int num[15000005];///质因子的个数
    int a[300005];///原数组
    int cnt;
    int maxxgcd;
    
    int gcd(int a,int b)
    {
        if(b==0)
            return a;
        return gcd(b,a%b);
    }
    
    void init()
    {
        memset(vis,true,sizeof(vis));
        cnt=0;
        for(int i=2;i<10086;i++)
        {
            if(vis[i])
                prime[cnt++]=i;
            for(int j=0;j<cnt && prime[j]*i<10086;j++)
            {
                vis[ i*prime[j] ]=false;
                if(i%prime[j]==0)
                    break;
            }
        }
    }
    
    int main()
    {
        init();
        while( scanf("%d",&n)!=EOF )
        {
            memset(num,0,sizeof(num));///每次清0
            maxxgcd=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                maxxgcd=gcd( maxxgcd,a[i] );
            }
            for(int i=1;i<=n;i++)
                a[i]=a[i]/maxxgcd;
            int maxx=-1;
            for(int i=1;i<=n;i++)
            {
                int x=a[i];
                ///原本的错误代码是for(int j=0;j<cnt;j++) cnt至少也是1000级的,n*cnt直接超时
                for(int j=0;prime[j]*prime[j]<=x;j++)///避免找全部素数,减少时间
                {
                    if( x%prime[j]==0 )
                    {
                        num[ prime[j] ]++;///小素数直接用数组存
                        maxx=max( num[ prime[j] ],maxx);
                        while(x%prime[j]==0)
                            x=x/prime[j];
                    }
                    if(x==1)
                        break;
                }
                if(x!=1)///遍历完10000以内的素数后,如果x还大于1,则是大素数,大素数用map存
                {
                    num[x]++;
                    maxx=max(num[x],maxx);
                }
            }
            if(maxx==-1)///若没有不同的质因子,此时a[i]必然全部都是1,也就没办法获取任何一个素数因子,不会改变maxx
                printf("-1
    ");
            else
                printf("%d
    ",n-maxx);
        }
        return 0;
    }
  • 相关阅读:
    PowerDesigner 12小技巧-pd小技巧-pd工具栏不见了-pd修改外键命名规则-pd添加外键
    支付宝支付开发——当面付条码支付和扫码支付
    C#开发微信门户及应用(41)--基于微信开放平台的扫码登录处理
    ***微信 该连接无法访问问题解决办法
    JQuery 导入导出 Excel
    用PowerDesigner对现有的数据库反向工程建立E-R图
    js 停止事件冒泡 阻止浏览器的默认行为(阻止超连接 #)
    微信网页第三方登录原理
    C# 添加Windows服务,定时任务
    微信公众平台开发(104) 自定义菜单扫一扫、发图片、发地理位置
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/10754089.html
Copyright © 2011-2022 走看看