质数

质数

试除法判断质数 O(sqrt(n))

时间复杂度是根号n

bool is_prime(int x)
{
	if(x < 2) return false;
	for(int i = 2; i <= x / i; i ++) // i <= x/i 要取等
	{
		if(x % i == 0) return false;
	}
	return true;
}

试除法分解质因数 O(sqrt(n))

时间复杂度是根号n

一个数x一定有且只有一个大于sqrt(x)的质因数(如果有两个大于根号x的质因数,相乘结果大于x,显然不成立)

下面的这个函数每次的i都可以保证一定是质数。每次x都变小了,如果i能被2到i-1的数整除,那么x一定能被2到i-1中的数整除,因为x是i的倍数(n能被i整除)。在迭代到i之前,<=i-1的合数已经被肢解了

// 按照质因数从小到大的顺序输出每个质因数的底数和指数
void divide(int x)
{
    for(int i = 2 ; i <= x / i ; i ++)
    {
        if(x % i == 0)
        {
            int s = 0; // 保存质因数的指数
            while(x % i == 0)
            {
                x /= i;
                s ++;
            }
            
            cout << i << ' ' << s << endl;
        }
    }
    if(x > 1) cout << x << ' ' << 1 << endl; // x一定有且只有一个大于sqrt(x)的质因子
}

筛素数(线性筛法) O(n)

线性筛素数的核心是:根据最小质因子来筛除

int primes[N],cnt,n;
bool st[N];

// 筛2~n中的素数
    for(int i = 2 ; i <= n ; i ++)
    {
        if(!st[i]) primes[cnt ++] = i; // 如果i没有被筛除,i为素数
        for(int j = 0; primes[j] * i <= n; j ++) // 因为筛的是2~n的,大于n就没有意义了
        {
            st[primes[j]*i] = true; // 根据最小质因子去筛除
            if(i % primes[j] == 0) break; // primes[j]是i的最小质因子,primes[j]*i的最小质因子不再是primes[j+1]*i,就不能再根据最小质因子筛素数,break
        }
    }
posted @ 2022-08-09 13:16  r涤生  阅读(45)  评论(0)    收藏  举报