GCD与素数筛总结

姓名: 王薪宇
赛道: 普及
类型: 算法技能

【GCD与素数筛总结】

今天学的东西不是特别难,但还是记录一下学的知识 :grin:

1. GCD

  • GCD定义
    GCD即最大公约数,一般记m,n的GCD为 \gcd(m,n)
    数学定义:若 g|m,g|n 且g最大,则称 g\gcd(m,n)
    集合定义:若 M 为数 m 的约数集合, Nn 的约数集合, G\gcd(m,n) 的约数集合,则有 G=M \cap N
    质因数分解定义:设 m=a_1^{k_1}·a_2^{k_2}·...·a_n^{k_n},n=a_1^{c_1}·a_2^{c_2}·...·a_n^{c_n}(k,c\ge 0),则 \gcd(m,n)=a_1^{\min(k_1,c_1)}·a_2^{min(k_2,c_2)}·...·a_n^{\min(k_n,c_n)}
  • GCD求解
    可用欧几里得算法(辗转相除法)求解
    具体来说,就是如果记 r=m-kn (相当于 r = m \mod n , k 为常数),则有 \gcd(m,n)=\gcd(n,r)
    证明:
    如果记 \gcd(m,n)=\gcd(n,r)=g ,则 g|m,g|kn ,因此 g|(m-kn) 。由于 r=m-kn,所以我们可以得到 g|r 。由于 g|n,g|r,所以 gcd(n,r)=g=gcd(m,n),证毕。
    代码:
int gcd(int x,int y) {
	if(y == 0) return x;
	return gcd(y,x % y);
}

时间复杂度 O(\log n) ,空间复杂度 O(1)

2. 质数筛

  • 埃氏筛
    主要思路就是“质数的倍数是合数”。记 np_i 表示 i 是否为合数,每次当 np_i=0 时,将 i 塞入答案数组,同时将 i 的倍数标记为合数。
    代码:
int n;
bool np[N];
vector<int> prime;
int main() {
    ……
    for(int i = 2;i <= n;i++) {
		if(!np[i]) {
			prime.push_back(i);
			for(int j = 2;j*i <= n;j++) {
				np[j*i] = 1;
			}
		}
	}
    ……
}

时间复杂度 O(n \log\log n) ,空间复杂度 O(n)

  • 线性筛
    埃氏筛虽然已经足够快了 \log\log n 可以当常数) ,但还有一些优化空间。
    我们可以注意到,在埃氏筛中,有亿些合数被重复标记,很浪费时间。我们可以让每个合数被自己最小的质因数筛掉,这样可以把复杂度降到线性。
int n;
bool np[N];
vector<int> prime;
int main() {
    ……
    for(int i = 2;i <= n;i++) {
        if(!np[i]]) {
            prime.push_back(i);
        }
        for(int j : prime) {
            if(j*i>n) break;
            np[j*i] = 1;
            if(i%j==0) break;
            // 由于 prime 里面质数是从小到大的
            //所以 i 乘上其他的质数的结果一定会被
            // j 的倍数筛掉,就不需要在这里先筛一次
           // 所以这里直接 break掉就好了
        }
    }
    ……
}

时间复杂度 O(n) ,空间复杂度 O(n)
(这玩意还能求很多积性函数值,这个以后再说。)

写总结不易,望大佬点赞 :pray:,谢谢!

参考文献:信友队课件,OI-wiki

原贴链接: 数论L1 GCD、素数筛总结 - 经验分享区 - 信友队论坛 (xinyoudui.com)

4 个赞

把你的
image
这个位置改为普及组

3 个赞

image

3 个赞

gcd有函数的,其实

int gcd(int x,int y) {
	if(y == 0) return x;
	return gcd(y,x % y);
}

这一部分可以简化为

int n=_gcd(x,y);

这里n是x,y的gcd。

当然你那样写也没毛病,可以更加理解gcd函数。

3 个赞

可以加个欧拉函数和莫比乌斯函数的筛法(虽然不是普及的)

2 个赞

Orz

1 个赞

是两个下划线吧………

1 个赞

啊对对对,写错了

3 个赞

@王薪宇 不懂就问,vetor是什么,不是vector吗

1 个赞

呃啊啊……打错了……抱歉

已经改正