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;
    }
  • 相关阅读:
    17 python学习笔记-异常处理
    二、如何使用postman做接口测试笔记(二)
    16 python学习笔记-使用yagmail模块发送邮件
    15 python学习笔记-多进程multiprocessing
    14 python学习笔记-多线程threading
    用HTML5构建一个流程图绘制工具
    百度地图API绘制带头箭头的折线
    使用JsPlumb绘制拓扑图的通用方法
    SQL Server 2008启用sa账户
    eclipse/ggts/myeclipse清除SVN用户名和密码
  • 原文地址:https://www.cnblogs.com/liuzhanshan/p/6287897.html
Copyright © 2011-2022 走看看