您的位置:首页 > 其它

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

2014-04-28 16:28 288 查看

这种问题一般都是给出限制条件:给你一个数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<stdio.h>
#include<math.h>

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<stdio.h>
#include<math.h>
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<stdio.h>
#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: