定义简分数为,分母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++实现