zoukankan      html  css  js  c++  java
  • hdu2588 gcd 欧拉函数

    GCD

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1567    Accepted Submission(s): 751


    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
     题目大意:
    数据量太大,用常规方法做是行不通的。后来看了别人的解题报告说,先找出N的约数x,

              并且gcd(x,N)>= M,结果为所有N/x的欧拉函数之和。

              因为x是N的约数,所以gcd(x,N)=x >= M;

       设y=N/x,y的欧拉函数为小于y且与y互质的数的个数。

       设与y互质的的数为p1,p2,p3,…,p4

       那么gcd(x* pi,N)= x >= M。

              也就是说只要找出所有符合要求的y的欧拉函数之和就是答案了。

    至于为何用ans+=Euler(n/i0而不是直接加n/i,这便是为了查重,防止出现重复
    只加满足gcd(k*x,n)==x的个数,不过如果直接遍历找约数遍历的量太大,同样会
    TLE,因此可以把区间右坐标变成sqrt(n),同时判断i和n/i即可,特别注意num*num=n
    的情况要单独处理。
    代码:
    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    int kase=0;
    LL Euler(LL n)
    {
        LL ans=n;
        for(int i=2;i*i<=n;i++)
        {
            if(n%i==0)
            {
                ans-=ans/i;
                while(n%i==0) n/=i;
            }
        }
      if(n>1) ans-=ans/n;
      return ans;
    }
    int main()
    {
        int t;
        cin>>t;
        __int64 n,m;
        while(t--)
        {
            kase=0;
            scanf("%I64d%I64d",&n,&m);
            int num=(int)sqrt(n+0.5);
            //cout<<num<<endl;
            for(int i=1;i<num;i++)
            {
                if(n%i==0)
                {
                    if(n/i>=m)
                    kase+=Euler(i);
                    if(i>=m)
                    kase+=Euler(n/i);
                }
            }
            //cout<<kase<<endl;
           // cout<<Euler(100)<<endl;
            if(num*num==n&&num>=m) kase+=Euler(num);
            cout<<kase<<endl;
        }
        return 0;
    }
     
  • 相关阅读:
    网页页面合适的大小
    Spring IO Platform简介及示例
    Spring Boot 单元测试详解+实战教程
    Spring Boot日志集成
    Spring Boot 16 条最佳实践
    Spring Boot自动配置原理、实战
    Spring Boot自动配置
    Windows10 IME占用过高临时解决办法
    GitLab版本管理
    大型系统重构的步骤梳理
  • 原文地址:https://www.cnblogs.com/xuejianye/p/5608433.html
Copyright © 2011-2022 走看看