最小公倍数和最大公因数

最小公倍数和最大公因数

LCM和GCD的基本关系

最小公倍数LCM最小公因数GCD

$$
LCM(a, b) = \frac{ab}{GCD(a,b)}
$$
我们根据这个关系就可以用GCD求LCM

辗转相除法求GCD

辗转相除法是由欧几里得提出来的,基本公式有两个:

①a > b

$$
GCD(a,b) = GCD(a-b, b)
$$

②所有情况

$$
GCD(a,b) = GCD(amodb, b)
$$
通过这两个公式就可以用递归的方法写出代码

代码1:

#include<bits/stdc++.h>
using namespace std;
int gcd(int a, int b){
	if(a % b == 0 || b % a == 0) return min(a, b);
	if(a > b) return gcd(a-b, b);
	else return gcd(a%b, b);
}
int main(){
	int x, y;
	scanf("%d%d", &x, &y);
	int ans = gcd(x, y);
	printf("%d", ans);
	return 0;
}

代码2:

#include<bits/stdc++.h>
using namespace std;
int gcd(int a, int b){
	if(a < b) swap(a, b);
	if(a % b == 0) return b;
	return gcd(a%b, b);
}
int main(){
	int x, y;
	scanf("%d%d", &x, &y);
	int ans = gcd(x, y);
	printf("%d", ans);
	return 0;
}

埃氏筛和欧式筛

埃氏筛和欧式筛都是通过筛选法有序的输出质数

埃氏筛

基本思路是用2、3、5、7等质数的倍数去掉,剩下的就是质数

代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,i,j;
    bool p[100001];
    memset(p,true,sizeof(p));
    p[1] = false;
    scanf("%d", &n);
    cout << 2; 
    for(i = 2; i <= sqrt(n); i++)
         if(p[i])  
            for(j = 2; i*j <= n; j++) 
                p[i*j] = false;
    for(i = 3; i <= n; i++)  
        if(p[i]) printf(" %d", i);
    cout << endl;
    return 0;
}

欧式筛

欧式筛又叫欧拉筛

埃氏筛存在重复筛的情况,如30会被2(15)、3(10)和5(*6)筛三次。
如何更快速地筛出一定上限内的素数?

下面这种方法(欧拉筛)可以保证范围内的每个合数都被删掉(在 bool 数组里面标记为非素数),而且任一合数只被:

“最小质因数 × 最大因数(非自己) = 这个合数”

的途径删掉。由于每个数只被筛一次,时间复杂度为O(n)。

代码:

#include<iostream>
#include<cstdio>
#include<cstring> 
using namespace std;
bool isPrime[100000010];
//isPrime[i] == 1表示:i是素数
int Prime[6000010], cnt = 0;
//Prime存质数、质数表 

void GetPrime(int n){
    memset(isPrime, 1, sizeof(isPrime));
    //以“每个数都是素数”为初始状态,逐个删去
    isPrime[1] = 0;//1不是素数
    for(int i = 2; i <= n; i++){
        if(isPrime[i])//没筛掉 
            Prime[++cnt] = i; //i成为下一个素数
        for(int j = 1; j <= cnt && i*Prime[j] <= n/*不超上限*/; j++) 
        {
            //从Prime[1],即最小质数2开始,逐个枚举已知的质数,并期望Prime[j]是(i*Prime[j])的最小质因数
            //当然,i肯定比Prime[j]大,因为Prime[j]是在i之前得出的
            isPrime[i*Prime[j]] = 0;
            if(i % Prime[j] == 0)//i中也含有Prime[j]这个因子
                break; //重要步骤。见原理
        }
    }
}
int main()
{
    int n, ans = 0;
    scanf("%d", &n);
    GetPrime(n);
    for(int i=1;i<=n;i++)
        if(Prime[i])
            ans++;
    printf("%d", ans);
    return 0;
}
posted @   SuperMax08  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示