求1~N的所有即约分数
公约数求法:可以使用欧几里得除法求得公约数
算法原理:
a,b为两个整数,a>b
a除以b的商q1和余数r1
如果r1为0,则最大公约数就为b
如果不为0,则继续使用b除以r取商为q2,余r2
如果r2为0,则最大公约数是r1,
如果不为0,则继续使用r2除以r1
递归思想,始终是上一次的除数除以上一次的余数,然后判断是否本次余数为0否,为0,则返回除数
gcd(a,b)
return gcd(b,a%b);
当然,递归要加终止条件
完整版
int gcd(int a,int b )
{
if (b==0) return a;
return gcd(b,a%b);
}
最终代码:
#include<bits/stdc++.h>
using namespace std;
int gcd(int a,int b);
signed main()
{
int ans=0;
for(int i=1;i<=2020;i++)
{
for(int j=1;j<=i;j++)
//if(__gcd(i,j)==1) ans++;
if(gcd(i,j)==1) ans++;
}
cout<<2*ans-1<<endl;
return 0;
}
int gcd(int a,int b )
{
if (b==0) return a;
return gcd(b,a%b);
}
这里,最小公倍数就也很好计算了,
两个数相乘,除以最大公约数就是最小公倍数
改进算法
求即约分数,即要求分子与分母互质,互为质数。根据数论知识,1~n中与n互质的数的个数称为欧拉函数,记作phi[n]
。
唯一分解定理,任何一个数,要么本身是质数,要么可以分解为有限个质数的乘积。
根据欧拉公式和唯一分解定理,可得算法如下:
唯一分解定理
```cpp
//唯一分解定理,能够把任意一个数分解成有限个质数的相乘
int getPrime(int p[],int n)
{
int k=0;//记录质数的个数
for(int i=2;i*i<=n;i++)
{
if(n%i==0) p[++k]=i;//如果能够被除掉,说明i就是其一个质数
while(n%i==0) n/=i;//等同于n=n/i,出去其重复因子
}
if(n>1) p[++k]=n;//前面没有一个数满足要求,则这个数质数因子只有是n本身了
return k;
}
```
求Euler函数
```cpp
//求解欧拉函数
int getEuler(int n)
{
int phi=n;
int k=getPrime(P,n);
for(int i=1;i<=k;i++)
{
phi=phi-phi/P[i];
}
return phi;
}
```
全部代码如下:
#include<bits/stdc++.h>
using namespace std;
int P[2020]={0};
//唯一分解定理,能够把任意一个数分解成有限个质数的相乘
int getPrime(int p[],int n)
{
int k=0;//记录质数的个数
for(int i=2;i*i<=n;i++)
{
if(n%i==0) p[++k]=i;//如果能够被除掉,说明i就是其一个质数
while(n%i==0) n/=i;//等同于n=n/i,出去其重复因子
}
if(n>1) p[++k]=n;//前面没有一个数满足要求,则这个数质数因子只有是n本身了
return k;
}
//求解欧拉函数
int getEuler(int n)
{
int phi=n;
int k=getPrime(P,n);
for(int i=1;i<=k;i++)
{
phi=phi-phi/P[i];
}
return phi;
}
int main()
{
int ans=0;
int ans1=0;
ans=getPrime(P,2020);
for(int i=1;i<=2020;i++)
ans1+=getEuler(i);
cout<<2*ans1-1<<endl;
return 0;
}