hdu 3388 Coprime 容斥原理 二分查找

Coprime

刚开始不知道用二分,因为没有发现序列单调不下降的性质;
留意二分查找需找到下界。
二分查找起点的右边界取m*n是不够的,实际查找到的结果可能远大于该值。

/** Aug 27, 2015 9:25:32 PM
 * PrjName:hdu3388
 * @author Semprathlon
 */
import java.io.*;
import java.util.*;
public class Main {

    /**
     * @param args
     */
    static Vector v1=new Vector();
    static Vector v2=new Vector();
    static HashSet st=new HashSet();
    static Integer[] fac=new Integer[0];
    static Vector get_prime_factor(int n){
        Vector res=new Vector();
        res.clear();
        for(int i=2;i*i<=n;i++)
            if (n%i==0){
                res.add(i);
                while(n%i==0)
                    n/=i;
            }
        if (n>1) res.add(n);
        return res;
    }
    static long check(long n){
        long res=0L;
        int m=fac.length;
        for(int i=1;i<(1L<long tmp=1L;
            boolean tag=false;
            for(int j=0;jif (((1L<0L){
                    tmp*=fac[j].longValue();
                    tag^=true;
                }
            res+=tag?n/tmp:-n/tmp;
        }
        return n-res;
    }
    static long bisearch(long low,long high,long key){
        long l=low,r=high,mid;
        while(l>1;
            if (check(mid)>=key)
                r=mid;
            else
                l=mid+1;
        }
        return l;
    }
    public static void main(String[] args) throws IOException{
        // TODO Auto-generated method stub
        InputReader in=new InputReader(System.in);
        PrintWriter out=new PrintWriter(System.out);
        int T=in.nextInt(),cas=0;
        while(T-->0){
            int m=in.nextInt();
            int n=in.nextInt();
            int k=in.nextInt();
            v1=get_prime_factor(m);
            v2=get_prime_factor(n);
            st.clear();
            for(Integer e:v1.toArray(new Integer[0]))
                st.add(e);
            for(Integer e:v2.toArray(new Integer[0]))
                st.add(e);
            fac=st.toArray(new Integer[0]);
            out.println("Case "+(++cas)+": "+bisearch(1, 0x3f3f3f3f3f3f3f3fL, k));
        }
        out.flush();
        out.close();
    }

}

较为神奇的是,把以上代码的check()函数(实现容斥原理的计算)替换为以下实现后,效率大有提升。

static long check(long n,int low){
        long sum=0L;
        for(int i=low;isum+=n/fac[i].longValue()-check(n/fac[i].longValue(),i+1);
        return sum;
    }

你可能感兴趣的:(ACM)