赞
踩
一、定义
若一个正整数无法被除1和它自身以外的自然数整除,则该数为质数(或素数),否则该数为合数。
1既不是质数也不是合数。
由定义可得质数的一个性质:只有1和它本身两个因数。
补充:对于一个足够大的整数N,不超过N的质数大约有N/㏑N个。即每㏑N个数中有1个质数。
二、判定质数
根据定义:素数就是一个数除了1 和他本身没有其他因数的数叫做质数。
于是我们对于一个N,可以可以从2枚举到N−1,从而判断这个数是不是质数。
bool Is_prime(int n){
if(n==1) return false;
if(n==2) return true;
for(int i=2;i<n;i++)
if(n%i==0) return false;
return true;
}
时间复杂度O(n);
对于上述程序显然不能满足我们的需求,如N较大时,这样的程序肯定容易超时,要想办法优化以上程序。
我们不难发现N的因数是成对出现的,所以对于任何一个整数N,我们只需要从1枚举到sqrt(N)就可以了。
于是代码如下:
bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i <= x / i; i ++ )//
if (x % i == 0)
return false;
return true;
}
时间复杂度o(sqrt(n))
ps.关于i<=n/i : 如果当i很大,还直接计算i*i时,可能会爆int,而计算n/i就没有这个问题。
AcWing 866. 试除法判定质数
给定n个正整数ai,判定每个数是否是质数。
输入格式
第一行包含整数n。
接下来n行,每行包含一个正整数ai。
输出格式
共n行,其中第 i 行输出第 i 个正整数ai是否为质数,是则输出“Yes”,否则输出“No”。
数据范围
1≤n≤100,
1≤ai≤2∗109
输入样例:
2
2
6
输出样例:
Yes
No
#include <iostream> #include <algorithm> using namespace std; bool is_prime(int x) { if (x < 2) return false; //列出i较小的因数 for (int i = 2; i <= x / i; i ++ )//且是i的因数 if (x % i == 0) return false; return true; } int main() { int n; cin >> n; while (n -- ) { int x; cin >> x; if (is_prime(x)) puts("Yes"); else puts("No"); } return 0; }
三、分解质因素
任何一个大于1的自然数 N,如果N不为质数,那么N可以唯一分解成有限个质数的乘积,即:
这里P1<P2<P3…<Pn均为质数,其中指数ai是正整数。
这里有个性质:n中最多只含有一个大于sqrt(n)的因子。证明通过反证法:如果有两个大于sqrt(n)的因子,那么相乘会大于n,矛盾。证毕
于是我们发现最多只有一个大于sqrt(n)的因子,对其进行优化。先考虑比sqrt(n)小的,代码和质数的判定类似
最后如果n还是>1,说明这就是大于sqrt(n)的唯一质因子,输出即可。
我们可以扫描2~sqrt(N)之间的每一个整数d,若d能整除N,则从N中除掉所有的因子d,同时累计除去的d的个数。
因为一个合数的因子一定在扫描到这个合数之前就从N中被除掉了,所以在上述过程中能整除N的一定是质数,最终就得到了质因数分解的结果,易知时间复杂度为O(sqrt(N))。
特别的,若N每有被任何2~sqrt(N)的数整除,则N是质数,无需分解。
时间复杂度: o(n) --> o(sqrt(n))
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;
}
//特判, 如果不是1那么就是那个较大的质因子.
//最多只有一个大于sqrt(n)的质因子.
if (x > 1) cout << x << ' ' << 1 << endl;
cout << endl;
}
AcWing 867. 分解质因数
给定n个正整数ai,将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。
输入格式
第一行包含整数n。
接下来n行,每行包含一个正整数ai。
输出格式
对于每个正整数ai,按照从小到大的顺序输出其分解质因数后,每个质因数的底数和指数,每个底数和指数占一行。
每个正整数的质因数全部输出完毕后,输出一个空行。
数据范围
1≤n≤100,
1≤ai≤2∗109
输入样例:
2
6
8
输出样例:
2 1
3 1
2 3
#include <iostream> #include <algorithm> using namespace std; 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; cout << endl; } int main() { int n; cin >> n; while (n -- ) { int x; cin >> x; divide(x); } return 0; }
四、筛质数
AcWing 868. 筛质数
给定一个正整数n,请你求出1~n中质数的个数。
输入格式
共一行,包含整数n。
输出格式
共一行,包含一个整数,表示1~n中质数的个数。
数据范围
1≤n≤106
输入样例:
8
输出样例:
4
把从2~n中的从小到大一次删掉每个数的倍数
#include <iostream> #include <algorithm> using namespace std; const int N= 1000010; int primes[N], cnt;// primes[]存储所有素数 bool st[N];// st[x]存储x是否被筛掉 void get_primes(int n) { for (int i = 2; i <= n; i ++ ) { if (st[i]) continue; primes[cnt ++ ] = i; for (int j = i + i; j <= n; j += i) st[j] = true; } } int main() { int n; cin >> n; get_primes(n); cout << cnt << endl; return 0; }
只把质数的倍数删掉
#include <iostream> #include <algorithm> using namespace std; const int N= 1000010; int primes[N], cnt;// primes[]存储所有素数 bool st[N];// st[x]存储x是否被筛掉 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)//将i的所有倍数删掉(循环放在里面) st[j] = true; } } } int main() { int n; cin >> n; get_primes(n); cout << cnt << endl; return 0; }
//算法核心:x 仅会被其最小质因子筛去 #include <iostream> #include <algorithm> using namespace std; const int N= 1000010; int primes[N], cnt; // primes[]存储所有素数 bool st[N];// st[x]存储x是否被筛掉 void get_primes(int n) { for (int i = 2; i <= n; i ++ ) { if (!st[i]) primes[cnt ++ ] = i; //假设primes[0]为n最小的质因子,i为最大的因数, //易知若primes[i]中i>0,则会进入循环后产生多余的标记。 for (int j = 0; primes[j] <= n / i; j ++ )//对于任意一个合数x,假设pj为x最小质因子,当i<x/pj时,一定会被筛掉 { //标记;primes[j]一定是primes[j]*i的最小质因子 st[primes[j] * i] = true; //表明primes[j]一定是i的最小质因子,没有必要再遍历,primes要小于等于i的最小质因子 //这样能保证每个数遍历一遍,而没有重复 if (i % primes[j] == 0) break; /* 1.i%pj == 0, pj定为i最小质因子,pj也定为pj*i最小质因子 2.i%pj != 0, pj定小于i的所有质因子,所以pj也为pj*i最小质因子 */ } } } int main() { int n; cin >> n; get_primes(n); cout << cnt << endl; return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。