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): 2836    Accepted Submission(s): 1479


    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
     
    题意:求gcd(i,n)>=m的个数( 1 <= i <= n )
    题解:起初想的是 n%i==0    ans+=n/i   之类的  但是会有很多重复的  只会基本的容斥原理 感觉太麻烦,也不会写。
       正解是 若n%a==0  n=a*b   那么gcd(n,i)=a     i=a*k   k与b互质 如果不互质的话gcd就不为a  所以ans+=euler(b)  然后折半枚举 因为除一下会出来两个因数。
       那么为什么这么写就没有重复的  难道没有 这种情况吗  n=a*b ,i=a*c  c属于与b互质的集合  n=c*b' , i=c*a    a属于与b'互质的集合( a!=c)  a*c就被算了两次吗?
       自己可以试着证明一下  假设上述是成立的  那么a与c都是n的因子  n可以写成 n=p1^2 * p2^2 * p3^1   与n/a互质的集合中有n的因子  说明a占用了n至少一个素因子的全部次幂
       那么c只可能是被占用的那个素因子的次幂。比如n=2*2*3*3*5  a=2*2  与n/a互质的数中有n的因子(c)2 和 4。那么与n/c的数中不可能包含a。 加设c=2 那么n/c=2*3*3*5 不存在
       假设c=4 与a相等 是同一种情况。
       综上,没有重复的元素。
     
     
    AC代码
      
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    #include <sstream>
    #include <algorithm>
    #include <string>
    #include <queue>
    #include <map>
    #include <vector>
    #include <set>
    #include <utility>
    #include <stack>
    using namespace std;
    const int maxn = 2e5+50,inf = 0x3f3f3f3f, mod = 998244353;
    const double epx = 1e-6;
    const double PI = acos(-1.0);
    typedef long long ll;
    ll euler(ll n)  //返回euler(n)
    {
        ll res=n,a=n;
        for(ll i=2; i*i<=a; i++)
        {
            if(a%i==0)
            {
                res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出 爆int
                while(a%i==0)
                    a/=i;
            }
        }
        if(a>1)
            res=res/a*(a-1);
        return res;
    }
    int main()
    {
        ll t,n,m;
        cin>>t;
        while(t--)
        {
            cin>>n>>m;
            ll ans=0;
            for(ll i=1;i*i<=n;i++)
            {
                if(n%i==0)
                {
                    if(i>=m)
                        ans+=euler(n/i);
                    if(n/i>=m&&i!=n/i)
                        ans+=euler(i);
                }
            }
            cout<<ans<<endl;
        }
    }

    如有错误 请大佬 指正~.~

  • 相关阅读:
    习题4.7利用vector实现数据复制
    习题4.18
    4.8编写一小段程序实现两vector是否相等的比较
    关于野指针
    学习c++的50条忠告
    c++头文件
    习题4.14
    容器和迭代器
    Android上C++对象的自动回收机制分析
    Windows下载Android源码
  • 原文地址:https://www.cnblogs.com/stranger-/p/8869852.html
Copyright © 2011-2022 走看看