zoukankan      html  css  js  c++  java
  • 最小集合(51nod 1616)

    A君有一个集合。

    这个集合有个神奇的性质。

    若X,Y属于该集合,那么X与Y的最大公因数也属于该集合。

    但是他忘了这个集合中原先有哪些数字。

    不过幸运的是,他记起了其中n个数字。

    当然,或许会因为过度紧张,他记起来的数字可能会重复。

    他想还原原先的集合。

    他知道这是不可能的……

    现在他想知道的是,原先这个集合中至少存在多少数。


    样例解释:

    该集合中一定存在的是{1,2,3,4,6}

    Input
    第一行一个数n(1<=n<=100000)。
    第二行n个数,ai(1<=ai<=1000000,1<=i<=n)。表示A君记起来的数字。
    输入的数字可能重复。
    Output
    输出一行表示至少存在多少种不同的数字。
    Input示例
    5
    1 3 4 6 6
    Output示例
    5
    /*
      自己还是太弱了……
      因为正着考虑一定会超时,随意考虑反着做,即枚举数字,看它是否属于这个集合(其实这点我想到了)。
      检验的方法很巧妙:看这个数在原集合中出现的倍数的gcd是否等于这个数,如果相等,则该数也属于集合。
    */
    #include<cstdio>
    #include<iostream>
    #define N 1000010
    using namespace std;
    int a[N],used[N],n;
    int gcd(int x,int y){
        if(!y)return x;
        return gcd(y,x%y);
    }
    int main(){
        scanf("%d",&n);int p=0,m=0;
        for(int i=1;i<=n;i++){
            int x;scanf("%d",&x);
            if(!used[x]){
                a[++p]=x;
                used[x]=1;
                m=max(m,x);
            }
        }
        n=p;
        for(int i=1;i<=m;i++){
            if(used[i])continue;
            int w=0;
            for(int j=i;j<=m;j+=i){
                if(used[j])w=gcd(w,j);
            }
            if(w==i)p++;
        }
        printf("%d",p);
        return 0;
    }
  • 相关阅读:
    闭包 (Closure)
    RSA算法
    HTTPS
    SSH
    HDU1754 I hate it_线段树(入门级别)
    HDU1166 敌兵布阵_线段树
    c++运算符优先级表
    归并排序练习.
    HDU 1969 精度二分
    uva10944 状态压缩bfs or DP
  • 原文地址:https://www.cnblogs.com/harden/p/6055383.html
Copyright © 2011-2022 走看看