欧拉函数和最大公约数的组合应用

          这种问题一般都是给出限制条件:给你一个数N(N一般很大),使得在1~N之间能够找到X使得X满足gcd( X ,  N  ) >= M,然后求解相关的问题。

         分析:这是一种统计类型的问题。比较容易想到的解法就是枚举gcd(X,N)的值, 对于枚举到的某个 gcd(X,N) 的值 d,如果 令 N = p * d,X = q * d,那么如果 gcd(X,N) = d,一定有 p,q 互质,又有 X <= N,则 q <= p,而这样的 q 的个数正好对应p的欧拉函数,即满足gcd(X,N) = d 的X的个数为N/d 的欧拉函数值。

应用1:求满足条件的X的个数。http://acm.hdu.edu.cn/showproblem.php?pid=2588

GCD

                                                                             Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

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
 
分析:对于这个问题,因为只需要求出满足题意的X的个数,所以可以枚举最大公约数d,而满足gcd(X,N) = d 的X的个数就是N/d的欧拉函数,把这些d对应的N/d的欧拉函数值求和即可。
#include
#include

int euler(int n)
{
    int m = (int)sqrt(n+0.5);
    int ans = n;
    for(int i = 2; i <= m; i++)
        if(n % i  == 0)
        {
            ans = ans / i * (i - 1);
            while(n % i == 0)
                n /= i;
        }
    if(n > 1)
        ans = ans / n * (n-1);
    return ans;

}

int main()
{
    int t, n, m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        int ans = 0;
        for(int i = 1; i * i <= n; i++) //枚举最大公因数
        {
            if(n % i == 0)
            {
                if(i >= m)
                    ans += euler(n/i);
                if(i * i != n && n / i >= m)
                    ans += euler(i);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}



应用2:求满足条件的gcd(X,N)的和。http://acm.nyist.net/JudgeOnline/problem.php?pid=998

Sum

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 3
描述

            给你一个数N,使得在1~N之间能够找到x使得x满足gcd( x ,  N  ) >= M,

求解gcd(x,N)的和

输入
多组测试数据

每行输出两个数N,M(N,M不超int)
输出
输出sum
样例输入
5 3
样例输出
5

分析:这个题要求gcd(X,N)的和,因为上一题已经求出了满足题意的个数,所以只需要在上一题的基础上乘以最大公约数就是最终答案。

#include
#include
typedef long long LL;

LL euler(LL n) //n的欧拉函数值
{
    LL ans = n;
    for(LL i = 2; i * i <= n; i++)
        if(n % i  == 0)
        {
            ans = ans / i * (i - 1);
            while(n % i == 0)
                n /= i;
        }
    if(n > 1)
        ans = ans / n * (n-1);
    return ans;

}

int main()
{
    LL n, m;
    while(~scanf("%lld%lld",&n,&m))
    {
        LL ans = 0;
        LL tmp = (LL)sqrt(n+0.5);
        for(LL i = 1; i <= tmp; i++) //枚举最大公因数
        {
            if(n % i == 0)
            {
                if(i >= m)
                    ans += euler(n/i) * i;
                if(i * i != n && n / i >= m)
                    ans += euler(i) * (n / i);
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}

应用3:求所有满足条件的X的和。 http://acm.nyist.net/JudgeOnline/problem.php?pid=1007

GCD

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 3
描述
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,please answer sum of  X satisfies 1<=X<=N and (X,N)>=M.
输入
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 (1<=N<=10^9, 1<=M<=10^9), representing a test case.
输出
Output the answer mod 1000000007
样例输入
3
1 1
10 2
10000 72
样例输出
1
35
1305000

分析:这个题和前两个题基本上一样,只需要在枚举最大公约数d时,求出gcd(X,N) = d 的所有X的和即可。根据上面可以得出:满足条件的X个数有euler(N/d)个,所以只需要求出不超过N/d且与N/d互素的那些数的和,然后乘以d就是最大公约数为d时对应的部分结果。而不超过N/d且与N/d互素的那些数的和 = N/d * euler(N/d) / 2,注意当N/d = 1时,结果是1而不是0。了解了这些,就可以解决这个题了。

除了1、2以外,所有数的欧拉函数都是偶数。

如果k <= n 并且 (k,n) = 1, 那么(n-k, n) = 1; 

#include
#define mod 1000000007
typedef long long LL;

LL euler(LL n) //n的欧拉函数值
{
    LL ans = n;
    for(LL i = 2; i * i <= n; i++)
        if(n % i  == 0)
        {
            ans = ans / i * (i - 1);
            while(n % i == 0)
                n /= i;
        }
    if(n > 1)
        ans = ans / n * (n-1);
    return ans;

}

LL euler_sum(LL n) //求和n互素的数的和
{
    if(n == 1) return 1;
    return n * euler(n) / 2;
}

int main()
{
    int t;
    LL n, m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld",&n,&m);
        LL ans = 0;
        for(LL i = 1; i * i <= n; i++) //枚举最大公因数
        {
            if(n % i == 0)
            {
                if(i >= m)
                    ans = (ans + euler_sum(n/i) * i) % mod;
                if(i * i != n && n / i >= m)
                    ans = (ans + euler_sum(i) * (n / i)) % mod;
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}


你可能感兴趣的:(比赛题,数学题,数论,gcd)