(Problem 72)Counting fractions

Consider the fraction, n/d, where n and d are positive integers. If nd and HCF(n,d)=1, it is called a reduced proper fraction.

If we list the set of reduced proper fractions for d  8 in ascending order of size, we get:

1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8

It can be seen that there are 21 elements in this set.

How many elements would be contained in the set of reduced proper fractions for d  1,000,000?

题目大意:

考虑分数 n/d, 其中n 和 d 是正整数。如果 nd 并且最大公约数 HCF(n,d)=1, 它被称作一个最简真分数。

如果我们将d  8的最简真分数按照大小的升序列出来,我们得到:

1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5 , 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8

可知该集合中共有21个元素。
d  1,000,000的最简真分数集合中包含多少个元素?

算法一(超时):

优化技巧:

1、当分母n是素数,则以n为分母的最简真分数的数目为n-1

2、当分母和分子奇偶不同的时候,进一步检查分母和分子的最大公约数

#include<stdio.h>

#include<stdbool.h>

void swap(int* a, int* b)  //交换两值的函数

{

    int t;

    t = *a;

    *a = *b;

    *b = t;

} 

 

int gcd(int a, int b)  //求最大公约数函数

{

    int r;

    if(a < b) swap(&a, &b);

    while(b) {

        r = a % b;

        a = b;

        b = r;

    }

    return a;

}

 

bool prim(int n) //判断素数函数

{

    int i;

    for(i = 2; i * i <= n; i++) {

        if(n % i == 0)  return false;

    }

    return true;

}

 

bool fun(int a, int b)  //判断两整数奇偶是否相同

{

    return !((a & 1) & (b & 1));

}

 

void solve()

{

    int i, j, t;

    long long count = 0;

    for(i = 2; i <= 100000; i++) {

        if(i % 2 && prim(i)) {

            count += i - 1;

            continue;

        }

        count++;

        for(j = 2; j < i; j++) {

            if(fun(i,j) && (i % j != 0)) {

                t = gcd(i, j);

                if(t == 1) count++;  //如果i,j互素,符合

            }

        }

    }

    printf("%lld\n", count);

}

 

int main()

{

    solve();

    return 0;

}

 

算法二:

将1~1000000的整数分奇偶两部分计算,依然超时

#include<stdio.h>

#include<stdbool.h>



#define N 1000000

 

int gcd(int a, int b)  //求最大公约数函数

{

    int r;

    while(b) {

        r = a % b;

        a = b;

        b = r;

    }

    return a;

}

 

bool prim(int n) //判断素数函数

{

    int i;

    for(i = 2; i * i <= n; i++) {

        if(n % i == 0)  return false;

    }

    return true;

}

 

bool fun(int a, int b)  //判断两整数奇偶是否相同

{

    return !((a & 1) & (b & 1));

}

 

void solve()

{

    int i, j, t;

    long long count = 0;

    for(i = 2; i <= N; i += 2) {

        count++;

        for(j = 3; j < i; j += 2) { 

            t = gcd(i, j);

            if(t == 1) count++;

        }

        

    }

    for(i = 3; i < N; i += 2) {

        count++;

        if(prim(i)) {

            count += i - 1;

            continue;

        } else {

            for(j = 2; j < i; j++) {

                if(gcd(i, j)) count++;

            }

        }

        

    }

    printf("%lld\n", count);

}

 

int main()

{

    solve();

    return 0;

}

 算法三:

#include<stdio.h>

#include<stdbool.h>

#include<math.h>



#define N 1000001



bool a[N];



void Eratosthenes()

{

    int i, M, j;

    for(i = 2; i < N; i++) {

        a[i] = true;

    }

    M = (int)sqrt(N);

    for(i = 2; i <= M; i++) { 

        if(a[i]) {

            j = i * i;

            for(; j < N; j += i)

                a[j] = false;

        }

    }

}



int fun(int n)

{

    int t, i, count, j;

    t = n / 2;

    i = 2;

    count = n - 1;

    while(i <= t) {

        if(a[i]) {

            if(n % i == 0) {

                count--;

                for(j = i; j * i < n; j++) {

                    count--;

                }

            }

        }

        i++;

    }

    return count;

}

  

int main()

{

    int i;

    long long count = 0;

    

    Eratosthenes();



    for(i = 2; i < N; i++) {

        if(a[i]) {

            count += i - 1;

        } else {

            count += fun(i);

        }

    }

    printf("%lld\n", count);

    

    return 0;

}

 算法四:使用欧拉函数

//(Problem 72)Counting fractions

// Completed on Tue, 18 Feb 2014, 14:08

// Language: C11

//

// 版权所有(C)acutus   (mail: [email protected]) 

// 博客地址:http://www.cnblogs.com/acutus/



#include<stdio.h>

#include<math.h>

#include<stdlib.h>

#include<stdbool.h>



#define N 1000001



int phi[N];     //数组中储存每个数的欧拉数



void genPhi(int n)//求出比n小的每一个数的欧拉数(n-1的)

{

    int i, j, pNum = 0 ;

    memset(phi, 0, sizeof(phi)) ;

    phi[1] = 1 ;

    for(i = 2; i < n; i++)

    {

        if(!phi[i])

        {

            for(j = i; j < n; j += i)

            {

                if(!phi[j])

                    phi[j] = j;

                phi[j] = phi[j] / i * (i - 1);

            }

        }

    }

}



void solve()

{

    int i;

    long long ans =0;

    for(i = 2; i < N; i++) {

        ans += phi[i];

    }

    printf("%lld\n", ans);

}



int main()

{

    genPhi(N);

    solve();

    return 0;

}
Answer:
303963552391

你可能感兴趣的:(action)