[OJ]分数个数问题--采用欧拉公式

定义简分数为,分母d>分子n,且不可以再约分。
如果我们把d≤6的所有简分数以从小到大的顺序排列,则有:
1/6,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5,5/6可以看到这个集合中包含的分数有11个。给定d,求这个最简分数集合中包含有多少个分数?
在这里插入图片描述
解决方案:
1.暴力求解,遍历2<=d之间的所有数,对于每一个数,通过辗转相除法,判断最大公约数是否为1,如果是,则计数次数加1。

#include<iostream>
using namespace std;

int DivisionAlgorithm(int a,int b)
{
    bool flag=false;
    if(b==0)
    {
        return a;
    }
    else
    {
        return DivisionAlgorithm(b,a%b);
    }
    
}

int SimpleFraction(int &d)
{
    int count=d-1;//记录当分子为1时的个数,减去1
    for (int j=d;j>=2;j--)
    {
        for (int i=2;i<j;i++)//先找到素数
        {
            if (DivisionAlgorithm(j,i)==1)//最大公约数为1
            {
                count++;
            }
        }
    }
    return count;
}



int  main()
{
    int d;
    cin>>d;
    int num=SimpleFraction(d);
    cout<<num<<endl;
    return 0;
}

在这里插入图片描述
在这里插入图片描述
对于一个数d,如果这个数较小,则可以采用上述方法。但是这里2<=d<=10^5,当输入10的5次方时,即100000,会导致超时,因此不能覆盖全部测试用例。

2.这里1/6,1/5,1/4,1/3,2/5,1/2,3/5,2/3,3/4,4/5,5/6都是互为质数,可以根据欧拉公式求解

采用欧拉函数进行求取
对正整数n,欧拉函数是小于等于n的正整数中与n互质的数的数目.
欧拉函数Euler(n):求[2,n]中有多少个数与n互素
直接利用公式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)……(1-1/pn)
其中:
pi为x的素因数
每个素因数只用一次
比如90=2 * 3^2 * 5
φ(90) = 90 * (1-1/2) * (1-1/3) * (1-1/5)
φ(1)=1(唯一和1互质的数(小于等于1)就是1本身)
如果不同的整数X和Y的最⼤公约数为1,则称X和Y为互质数。Y的最⼤公约数为1,则称X和Y为互质数。显然,X和Y互质等价于Y和X互质。给出整数N,求1~N之间,有多少个数对
(X,Y)是互质数。
例如N=5时,(1,2) , (1,3), (1,4), (1,5), (2,3), (2,5), (3,4), (3,5), (4,5)共9对数是互质数。

采用欧拉公式求解,只需要for循环一次,极大的降低了时间复杂度。

/*
 * @Author: error: git config user.name && git config user.email & please set dead value or install git
 * @Date: 2022-08-03 23:40:41
 * @LastEditors: error: git config user.name && git config user.email & please set dead value or install git
 * @LastEditTime: 2022-08-04 18:15:59
 * @FilePath: \C++\testC++\fractionNum.cpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include<iostream>
#include<cmath>
using namespace std;

/*
辗转相除法:
穷举到n,一一判断该数与n的最大公约数是否为1,即是否为互质
结论:可以实现,但时间复杂度太高,OJ提交6分,会超时
采用欧拉函数进行求取
对正整数n,欧拉函数是小于等于n的正整数中与n互质的数的数目.
欧拉函数Euler(n):求[2,n]中有多少个数与n互素

直接利用公式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn)

其中:

pi为x的素因数
每个素因数只用一次
比如90=2 * 3^2 * 5
φ(90) = 90 * (1-1/2) * (1-1/3) * (1-1/5)
φ(1)=1(唯一和1互质的数(小于等于1)就是1本身)
如果不同的整数X和Y的最⼤公约数为1,则称X和Y为互质数。Y的最⼤公约数为1,则称X和Y为互质数。显然,X和Y互质等价于Y和X互质。给出整数N,求1~N之间,有多少个数对
(X,Y)是互质数。
例如N=5时,(1,2) , (1,3), (1,4), (1,5), (2,3), (2,5), (3,4), (3,5), (4,5)共9对数是互质数。
*/

//辗转相除法,递归,导致时间复杂度太大
int gcd(int a,int b)
{  
    if(b==0)
    {
        return a;
    }
    else
    {
        return gcd(b,a%b);
    }
    
}

//辗转相除法,非递归
int DivisionAlgorithm(int a,int b)
{
    int k;
    while((k=a%b)!=0)
    {
        a=b;
        b=k;
    }
    return b;
}

///欧拉函数,求值
int Euler(int n)
{
    int ans=n;
    for(int i=2;i*i<=n;++i)
    {
        if(n%i==0)
        {
            ans=ans-ans/i;//x(1-1/p1)的变形
            while(n%i==0)//第一次找到的必为素因子
            {
                n/=i;//把该素因子全部约掉
            }

        }
    }
    if (n!=1) ans=ans-ans/n;
    return ans;
}



long SimpleFraction(int &d)
{
    long count=0;//记录当分子为1时的个数,减去1
    for (int i=d;i>1;--i)
    {
        int num=Euler(i);
        count+=num;
    }
    return count;
}



int  main()
{
    int d;
    cin>>d;
    long num=SimpleFraction(d);
    cout<<num<<endl;
    return 0;
}


在这里插入图片描述
欧拉
参考:欧拉公式C++实现

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值