前言
本文是关于质数的一些内容,希望能够对大家有帮助!!!
一、质数的基本内容
定义:
质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)。
质数的个数是无穷的。欧几里得的《几何原本》中有一个经典的证明。它使用了证明常用的方法:反证法。具体证明如下:假设质数只有有限的n个,从小到大依次排列为p1,p2,……,pn,设N=p1×p2×……×pn。如果 为素数,则 要大于p1,p2,……,pn,所以它不在那些假设的素数集合中。如果N+1为合数,因为任何一个合数都可以分解为几个素数的积;而N和N+1的最大公约数是1,所以不可能被p1,p2,……,pn整除,所以该合数分解得到的素因数肯定不在假设的素数集合中。因此无论该数是素数还是合数,都意味着在假设的有限个素数之外还存在着其他素数。所以原先的假设不成立。也就是说,素数有无穷多个。
模板:
试除法判定质数 —— 模板:
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;
}
试除法分解质因数 —— 模板:
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 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 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 = 0; primes[j] <= n / i; j ++ ){st[primes[j] * i] = true;if (i % primes[j] == 0) break;}}
}
二、例题
1.试除法判定质数
AC代码:
#include <bits/stdc++.h>
using namespace std;bool check(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 m;scanf("%d", &m);while (m -- ){int x;scanf("%d", &x);puts(check(x) ? "Yes" : "No");}return 0;
}
2.分解质因数
AC代码:
#include <bits/stdc++.h>
using namespace std;void solve(int n)
{for (int i = 2; i <= n / i; i ++ ){if (n % i == 0){int s = 0;while (n % i == 0){n /= i;s ++ ;}printf("%d %d\n", i, s);}}if (n > 1) printf("%d 1\n", n);puts("");
}int main()
{int m;scanf("%d", &m);while (m -- ){int x;scanf("%d", &x);solve(x);}return 0;
}
3、筛质数
AC代码1:
// 埃式筛
// 写法1
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int primes[N], cnt, n;
bool st[N];void solve()
{for (int i = 2; i <= n; i ++ ){if (!st[i]){primes[cnt ++ ] = i;for (int j = 2 * i; j <= n; j += i)st[j] = true;}}
}int main()
{scanf("%d", &n);solve();printf("%d\n", cnt);return 0;
}// 写法2
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int primes[N], cnt, n;
bool st[N];void solve()
{for (int i = 2; i <= n; i ++ ){if (!st[i]){primes[cnt ++ ] = i;for (int j = i; j <= n / i; j ++ )st[i * j] = true;}}
}int main()
{scanf("%d", &n);solve();printf("%d\n", cnt);return 0;
}
AC代码2:
// 线性筛
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int primes[N], cnt, n;
bool st[N];void solve()
{for (int i = 2; i <= n; i ++ ){if (!st[i]) primes[cnt ++ ] = i;for (int j = 0; j < cnt && primes[j] <= n / i; j ++ ){st[i * primes[j]] = true;if (i % primes[j] == 0) break;}}
}int main()
{scanf("%d", &n);solve();printf("%d\n", cnt);return 0;
}