zoukankan      html  css  js  c++  java
  • SPOJ:NO GCD (求集合&秒啊)

    You are given N(1<=N<=100000) integers. Each integer is square free(meaning it has no divisor which is a square number except 1) and all the prime factors are less than 50. You have to find out the number of pairs are there such that their gcd is 1 or a prime number. Note that (i,j) and (j,i) are different pairs if i and j are different.

    Input

    The first line contains an integer T(1<=T<=10) , the number of tests. Then T tests follows. First line of each tests contain an integer N. The next line follows N integers.

    Output

    Print T lines. In each line print the required result.

    Sample Input

    Sample Output

    1

    3

    2 1 6 

    Explanation

    gcd(1,2)=1

    gcd(2,1)=1

    gcd(2,6)=2, a prime number

    gcd(6,2)=2, a prime number

    gcd(1,6)=1

    gcd(6,1)=1

    gcd(2,2)=2, a prime number

    gcd(1,1)=1

    So, total of 8 pairs.

    题意:给定数组a[],求多少对(i,j),使得a[i],a[j]互质或者gcd是质数,保证a[]只有小于50的素因子,而且不含平方因子。

    思路:注意到只有15个素数,开始想到了用二进制来找互质的个数和有一个素因子的个数,但是复杂度好像还是过不去。第二天忍不住参考了vj上面的代码。。。

    主要问题在于,如何快速地求一个二进制的子集,即对i,求所有的j,j<=i&&(i|j)==i。后面地就不难。

    前辈写的是:

        for(i=0;i<M;i++){
                for(j=i;;j=(j-1)&i){        
                   s[i]+=num[j]; //关键,得到子集 
                   if(!j) break;
                }
            }

    时间大概是1.4e7。

    int times=0;
        for(i=0;i<M;i++){
           for(j=i;;j=(j-1)&i){        
              times++;
               if(!j) break;
           }
        }  
        cout<<times<<endl;

    。。。注意把0也要累加进去。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int M=1<<15;
    int num[M],s[M];
    int p[15]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
    int main()
    {
        int T,N,i,j,tmp; ll ans,x;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&N);
            memset(num,0,sizeof(num));
            memset(s,0,sizeof(s));
            for(i=1;i<=N;i++){
               scanf("%lld",&x); tmp=0;
               for(j=0;j<15;j++) if(x%p[j]==0) tmp+=1<<j;
               num[tmp]++;
            }
            for(i=0;i<M;i++){
                for(j=i;;j=(j-1)&i){        
                   s[i]+=num[j]; //关键,得到子集 
                   if(!j) break;
                }
            } ans=0;
            for(i=0;i<M;i++){
                ans+=(ll)num[i]*s[i^(M-1)];//互质 
                for(j=0;j<15;j++){ //刚好有一个素因子
                    if(i&1<<j){
                        ans+=(ll)num[i]*(s[i^(M-1)^(1<<j)]-s[i^(M-1)]);//减法保证这个素因子不被减去 
                    } 
                } 
            }
            cout<<ans<<endl; 
        }
        return 0;
    }
  • 相关阅读:
    ASP.NET Core的配置信息
    ASP .NET Core 建立列表和表单View
    ASP.NET Core 如何使用Mvc相关技术建立Controller、Tag Helper (下)
    MySQL日志突然暴涨
    MySQL函数索引及优化
    MySQL统计库表大小
    MySQL8.0窗口函数实践及小结
    MySQL按指定字符合并及拆分
    分享2个近期遇到的MySQL数据库的BUG案例
    mysql大表在不停机的情况下增加字段该怎么处理
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8966526.html
Copyright © 2011-2022 走看看