zoukankan      html  css  js  c++  java
  • hdu2588 GCD 给定n,m。求x属于[1,n]。有多少个x满足gcd(x,n)>=m; 容斥或者欧拉函数

    GCD
    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2155    Accepted Submission(s): 1093
    
    
    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
    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2588
    题意:给定n,m。求x属于[1,n]。有多少个x满足gcd(x,n)>=m;
    思路:
    x -> [1,n]
    
    d = gcd(x,n) >= m
    
    d肯定为n的约数。
    
    对一个确定的d = gcd(x,n);
    
    那么:gcd(x/d,n/d) = 1;
    
    满足上面式子的x为:f(n/d); f(y)表示y的欧拉函数。
    
    sigma(f(n/d)) (d为n的约数且d>=m);
    
    f(y) = y*(p1-1)/p1*(p2-1)/p2...*(pe-1)/pe;
    
    */
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #define LL long long
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    ll Euler(ll x)
    {
        ll n = x;
        for(int i = 2; i*i<=x; i++){
            if(x%i==0){
                n = n/i*(i-1);
                while(x%i==0)x/=i;
            }
        }
        if(x>1){
           n = n/x*(x-1);
        }
        return n;
    }
    vector<int> v;
    int main()
    {
        int T;
        int n, m;
        cin>>T;
        while(T--)
        {
            scanf("%d%d",&n,&m);
            v.clear();
            for(int i = 1; i*i<=n; i++){
                if(n%i==0){
                    if(i*i==n){
                        if(i>=m) v.push_back(i);
                    }
                    else{
                        if(i>=m) v.push_back(i);
                        if(n/i>=m) v.push_back(n/i);
                    }
                }
            }
            int len = v.size();
            int cnt = 0;
            for(int i = 0; i < len; i++){
                cnt += Euler(n/v[i]);
            }
            printf("%d
    ",cnt);
        }
        return 0;
    }
    
    容斥做法:
    /**
    题目:GCD
    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2588
    题意:给定n,m。求x属于[1,n]。有多少个x满足gcd(x,n)>=m;
    思路:
    
    显然d = gcd(x,n)中的d一定是n的约数。
    
    显然d = gcd(d,n); 先获得所有>=m的d;
    
    那么d的倍数为x=k*d,如果小于等于n,则一定也满足gcd(x,n)>=m;
    
    k = n/d; 如果对每个d这样计算,会有重复的计算。
    
    当d = 2, 3时候,x=6会多计算一次。
    
    所以要对所有的d进行容斥处理。
    
    问题转化为:n的约数为d,求解d>=m的所有的d在n范围内至少有一个是d的倍数的数有多少个。
    
    
    
    */
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #define LL long long
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    vector<int> v;
    int a[10004], z;  ///注意a数组要开大些,约数个数还是不是100就够的。
    ll gcd(ll a,ll b)
    {
        return b==0?a:gcd(b,a%b);
    }
    ll rc(ll n)
    {
        ll sum = 0;
        ll mult;
        int ones;
        int len = v.size();
        int m = (1<<len);
        //奇加偶减
        for(int i = 1; i < m; i++){
            ones = 0;
            mult = 1;
            for(int j = 0; j<len; j++){
                if(i&(1<<j)){
                    ones++;
                    mult = mult/gcd(mult,v[j])*v[j];
                    if(mult>n) break;
                }
            }
            if(ones%2==0){
                sum -= n/mult;
            }else
            {
                sum += n/mult;
            }
        }
        return sum;
    }
    int main()
    {
        int T;
        int n, m;
        cin>>T;
        while(T--)
        {
            scanf("%d%d",&n,&m);
            v.clear();
            z = 0;
            for(int i = 1; i*i<=n; i++){
                if(n%i==0){
                    if(i*i==n){
                        if(i>=m) a[z++] = i;
                    }
                    else{
                        if(i>=m) a[z++] = i;
                        if(n/i>=m) a[z++] = n/i;
                    }
                }
            }
            ///出去包含的,比如2,4那么4要去掉。以为4的倍数一定是2的倍数。
            sort(a,a+z);
            for(int i = 0; i < z; i++){
                int sign = 0;
                for(int j = 0; j < i; j++){
                    if(a[i]%a[j]==0){
                        sign = 1; break;
                    }
                }
                if(sign==0){
                    v.push_back(a[i]);
                }
            }
            printf("%lld
    ",rc(n));
        }
        return 0;
    }
    
    
     
  • 相关阅读:
    rest framework 认证 权限 频率
    rest framework 视图,路由
    rest framework 序列化
    10.3 Vue 路由系统
    10.4 Vue 父子传值
    10.2 Vue 环境安装
    10.1 ES6 的新增特性以及简单语法
    Django 跨域请求处理
    20190827 On Java8 第十四章 流式编程
    20190825 On Java8 第十三章 函数式编程
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/6844226.html
Copyright © 2011-2022 走看看