数学知识——质数

20240626

课程链接地址

数学知识一
数论——质数
866 质数判定
法一:
暴力法试除法

法二:
优化, d|n d整除n, 那么n/d一定能整除n
比如n=12, d=3可以, n/d= 4 也可以整除12
所以枚举较小的d 那么n/d一定是,不用枚举了 到n/i!!!
所以本来枚举n次, 现在根号n次

但是不推荐
写 I * I <= n 因为当i接近intmax,会i*i溢出,会变成一个负数 可以用Longlong也行
或者 I <= sqrt(n) 因为sqrt太慢了
写成 I <= n/I


#include<iostream>
#include<algorithm>


using namespace std;

// 法一:纯暴力法O(n) 过不了 会超时
bool is_prime1(int n){
    if(n < 2) return false;
    for(int i =2; i <= n; i ++){
        if( n % i == 0) return false;
    }
    return true;
}

// 法二: 根号n用n/i
bool is_prime2(int n){
    if(n < 2) return false;
    for(int i =2; i <= n / i ; i ++){
        if( n % i == 0) return false;
    }
    return true;
}
int main(){
    int n, a;
    cin >> n;
    
    while(n --){
        cin >> a;
        if(is_prime2(a)) printf("Yes\n");
        else printf("No\n");
    }
    
    return 0;
}


分解质因数 08:21

  1. 从小到大枚举所有数 会不会有问题:因为所有数= 合数+质数 不会 因为当枚举到i,已经把2到i-1的所有质因子都除干净了 因为i之前都n%之前的 !=0 跳过了没计数, =0的都除过了,所以不会出现合数,一定是已经除干净了 此时如果还满足n%i=0,那么 i一定是质数
  2. 优化 降时间复杂度:n中至多包含一个大于根号n的质因子, 因为如果两个,那么俩乘一块,一定大于n i<=n/I 这里注意最后单独处理这个大于根号n的质因子
  3. 注意: 上一题优化以后一定是O(根号n) 但是这题不一定是根号n 比如n = 2^k, 枚举 i=2 一直除干净k次= log2_n到n= 1,结束了

所以时间复杂度介于O log2_n ~O 根号n


// 暴力法
void divide1(int n){
    for(int i = 2; i <= n; i ++){
        // 枚举所有数= 质数+合数,但是合数已经被跳过,不计数
        // 已经是质数的都除干净了
        if(n % i == 0)  {
            // 满足的i次数
            int s = 0;
            while (n % i == 0)
            {
                // 辗转相除
                n /= i;
                s ++;
            }
            printf("%d %d\n", i, s);
        }
    }
}

// 优化法
void divide2(int n){
    for(int i = 2; i <= n/i; i ++){
        if(n % i == 0)  {
            // 满足的i次数
            int s = 0;
            while (n % i == 0)
            {
                // 辗转相除
                n /= i;
                s ++;
            }
            printf("%d %d\n", i, s);
        }
    }
    if(n > 1) printf("%d %d\n", n, 1);
    puts("");
}

int main(){
    int n, a;
    cin >> n;
    
    while(n --){
        cin >> a;
        divide2(a);
    }
    
    return 0;
}

筛 858 16:23 云里雾里的
20240627

  1. 删2所有倍数 依次往后删3 4 5 。。。的所有倍数
    剩下所有数就是质数 p不是2- (p-1)任何一个数的倍数!!!

  2. 删2 循环了 n/2次
    删3 循环n/3次
    求和调和级数!!高数忘了,c欧拉常数0.57796无限不循环常数 1/x求和lnx

  3. 优化埃式筛法
    不删所有数的倍数,只删质数的倍数
    for放for里!!
    因为不需要枚举判断2- p-1所有的数是不是p的约数
    只要判断其中的质数是不是p的约数就行,减少计算判断

    质数定理:1-n有n/lnn个质数 所以粗略O(nlnn/lnn)= o(n) 其实是o(nlog2log2n) 但基本上是O(n)级别,比如2^32, log2=32, log2=5, 埃式筛法,希腊人埃拉托斯特尼发明的

  4. 优化2——线性筛法
    每个合数只会被它最小质因子筛掉,从小到大枚举所有质数
    用质数把合数筛掉

    时间快一倍

    Pj =primes[j]
    比如x=12, pj =2 枚举到x/pj= 6 已经筛过了,每个数只被筛一次,不会重复,所以线性!!

    for没有必要加j<cnt,只用primes[j] <=n/i就行了

    听的乱七八糟云里雾里有点 数学知识题一定要会原理,自己推一遍

	
	#include<iostream>
	#include<algorithm>
	
	using namespace std;
	
	const int N = 1000010;
	
	int primes[N], cnt = 0;
	bool st[N];
	
	void get_primes(int n){
	    for(int i = 2; i <= n; i ++){
	        if (!st[i]){
	            primes[cnt ++ ] = i;
	            
	        }
	        for (int j = i + i; j <= n; j += i)
	            st[j] = true;
	    }
	}
	
	// 埃式筛法
	void get_primes2(int n){
	    for(int i = 2; i <= n; i ++)
	    {
	        if (!st[i]){
	            primes[cnt ++ ] = i;
	            for (int j = i + i; j <= n; j += i)
	                st[j] = true;
	        }
	    }
	}
	
	// 线性筛法
	void get_primes3(int n){
	    for(int i = 2; i <= n; i ++){
	        // 是质数就加
	        if(!st[i]) primes[cnt ++] = i; 
	        
	        // 从小到大 枚举当前所有质数,
	        for(int j = 0; primes[j] <= n/i; j ++){
	            st[primes[j] * i ] =true;
	            if( i % primes[j] == 0) break;  // primes[j]一定是i的最小质因子
	        }
	    }
	}
	
	int main(){
	    int n;
	    cin >> n;
	    
	    get_primes(n);
	    cout << cnt << endl;
	    return 0;
	}
	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值