zoukankan      html  css  js  c++  java
  • HDU2588--GCD(欧拉函数)

    Problem Description

    The greatest common divisor GCD(a,b) of two positive integers a and b,sometimes written (a,b),is the largest divisor common to a and b,For example,(1,2)=1,(12,18)=6.
    (a,b) can be easily found by the Euclidean algorithm. Now Carp is considering a little more difficult problem:
    Given integers N and M, how many integer X satisfies 1<=X<=N and (X,N)>=M.

    Input

    The first line of input is an integer T(T<=100) representing the number of test cases. The following T lines each contains two numbers N and M (2<=N<=1000000000, 1<=M<=N), representing a test case.

    Output

    For each test case,output the answer on a single line.

    Sample Input

    3
    1 1
    10 2
    10000 72

    Sample Output

    1
    6
    260

    Source

    ECJTU 2009 Spring Contest

    Recommend

    lcy

    题意:

    题目意思很简单,在X∈[1~N],存在多少个X使得GCD(X,N)>=M,统计X符合要求的个数。

    如果直接暴力遍历N次,每次操作的复杂度高达10^9,肯定会超时的。常规的方法肯定不行。

    ①首先,补充一下关于GCD()的一些基础知识。

      1,如果GCD(a,b)=c,则可以知道GCD(a/c,b/c)=1;(  GCD(a,b)=c  <=>  GCD(a/c,b/c)=1  )

      2,设GCD(a,b)=c,如果想要GCD(a,b*d)=c,用①_1可知,

        只需满足GCD(a/c,(b/c)*d)=1即可(这个限制既为,满足最大公约数的要求).

    ②然后,我们所要求的是GCD(X,N)>=M,也就是说我们要求一个GCD(X,N)=Z,的数,

      1,如果M==1,则可以知道在[1,N]中任意数X的GCD(X,N)>=1,所以符合要求的个数为N。

      2,如果M>1,则这个X一定是N的约数(大于1),或者是约数(大于1)的倍数 <--------- (只有如此,才能使得GCD(X,N)!= 1)

    ③再者,我们需要统计的数符合要求的X的个数呢?

      1,正如②_2可以知道GCD(N,X)=X,能够使得GCD()=X的数有约数(大于1)及约数的倍数两部分组成,记这个约数为X,则GCD(N,X*q)=X     (q>=1)

      只需要计算1~N中有多少个(X*q)即可。

      2,由①_2可知,要使得GCD(N,X*q)=X,需要满足GCD(N/X,q)=1.也就是统计1~N/X中有多少个数与N/X互质。

    求1~N中,有多少个与N互质的数,欧拉函数,SUM+=Eular(N/X);

    ④最后,如何不重复的统计其公约数为符合条件X的数呢?

    只要X不相同,且满足③_2条件,qX就不会相同。

    简单证明:

    设有N的两个约数a,b 且a<=b, 若有q1*a=q2*b,则gcd(N/a, q1*b)= b或b的倍数 != 1     <-----------------  N/a含有因子b,而q1*b也有因子b

     

    参考博客:http://www.cnblogs.com/LWF5201314614/p/4548132.html

    代码:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    int Eular(int N)
    {
        int sign=1,i;
        for(i=2;i*i<=N;i++)
        {
            if(N%i==0)
            {
                N/=i;sign*=i-1;
                while(N%i==0)
                {N/=i;sign*=i;}
            }
        }
        if(N>1)
        sign*=N-1;
        return sign;
    }
    int main()
    {
        int A,B,T,i,sign;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&A,&B);
            for(i=1,sign=0;i*i<=A;i++)/*分解约数*/
               if(A%i==0)       /*分解约数,同时判断两边*/
               {           /*如果为平方数则主需要判断一次*/
                    if(i>=B)
                        sign+=Eular(A/i);
                    if((A/i)!=i&&(A/i)>=B)/*判断是否为平方数*/
                        sign+=Eular(i);
               }
            printf("%d
    ",sign);/*输出答案*/
        }
        return 0;
    }
  • 相关阅读:
    linux 解压tgz 文件指令
    shell 脚本没有执行权限 报错 bash: ./myshell.sh: Permission denied
    linux 启动solr 报错 Your Max Processes Limit is currently 31202. It should be set to 65000 to avoid operational disruption.
    远程查询批量导入数据
    修改 MZTreeView 赋权节点父节点选中子节点自动选中的问题
    关于乱码的问题解决记录
    我的网站优化之路
    对设计及重构的一点反思
    我的五年岁月
    奔三的路上
  • 原文地址:https://www.cnblogs.com/liuzhanshan/p/6287897.html
Copyright © 2011-2022 走看看