质数判定
试除法:
若正整数N是合数,则存在一个能整除N的数T,且T <= sqrt(N)。
代码:
判断一个数是不是质数。
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<iostream>
#define int long long
using namespace std;
const int N = 1e3+10;
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;
}
signed main(){
int n; cin>>n;
cout<<is_prime(n)<<endl;
return 0;
}
筛法:
埃氏筛法:
从2开始,把每一个的倍数标记一下,被标记的一定不是质数,对于每一个数,从它的平方开始标记能完全筛出所有质数。
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
const int N = 1e3+10;
bool vis[N];
int primes[N],cnt;
void get_primes(int n){
memset(vis,false,sizeof(vis));
for(int i=2;i<=n;i++)
if(!vis[i]){
primes[cnt++] = i;
for(int j=i*i;j<=n;j+=i) vis[j] = true;
}
}
signed main(){
int n; cin>>n;
get_primes(n);
for(int i=0;i<cnt;i++) cout<<primes[i]<<endl;
return 0;
}
欧拉筛:
让每一个质因数被它的最小质因子标记。
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
const int N = 1e3+10;
bool vis[N];
int primes[N],cnt;
void ols(int n){
for(int i=2;i<=n;i++){
if(!vis[i]) primes[cnt++] = i;
for(int j=0;j<cnt && i*primes[j]<=n;j++){
vis[i*primes[j]] = true;
if(i % primes[j] == 0) break;
}
}
}
signed main(){
int n; cin>>n;
ols(n);
for(int i=0;i<cnt;i++) cout<<primes[i]<<endl;
return 0;
}
质因数分解:
唯一分解定理:任何一个大于1的数都能唯一分解为有限个质数的乘积。
N = p 1 c 1 ∗ p 2 c 2 ∗ . . . ∗ p m c m N = p_{1}^{c_1}*p_{2}^{c_2}*...*p_{m}^{c_m} N=p1c1∗p2c2∗...∗pmcm
结合试除法和埃氏筛的思想,枚举2~sqrt(n)的所有数d,去除掉当前值的所有因子d,并统计个数
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
const int N = 1e3+10;
int p[N],c[N],cnt;
signed main(){
int n; cin>>n;
for(int i=2;i<=n/i;i++){
if(n % i == 0){
p[++ cnt] = i;
while(n % i == 0) c[cnt] ++,n /= i;
}
}
if(n > 1) p[++ cnt] = n,c[cnt] = 1;
for(int i=1;i<=cnt;i++) cout<<p[i]<<" "<<c[i]<<endl;
return 0;
}
例题:
埃氏筛
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
const int N = 1e6+10;
bool vis[N];
//int primes[N],cnt;
int sum[N];
void get_primes(int n){
for(int i=2;i<=n;i++)
if(!vis[i]){
// primes[cnt++] = i;
for(int j=i*i;j<=n;j+=i) vis[j] = true;
}
}
signed main(){
int n,m; cin>>n>>m;
get_primes(m);
for(int i=2;i<=m;i++) {
sum[i] = sum[i-1];
if(!vis[i]) sum[i] ++;
}
while(n --){
int l,r; cin>>l>>r;
if(l >= 1 && l <= m && r >= 1 && r <= m && l <= r)
cout<<(sum[r] - sum[l-1])<<endl;
else cout<<"Crossing the line"<<endl;
}
return 0;
}
欧拉筛
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#include<iostream>
#include<cstring>
#define int long long
using namespace std;
const int N = 1e6+10;
int sum[N];
bool vis[N];
int primes[N],cnt;
void ols(int n){
for(int i=2;i<=n;i++){
if(!vis[i]) primes[cnt++] = i;
for(int j=0;j<cnt && i*primes[j]<=n;j++){
vis[i*primes[j]] = true;
if(i % primes[j] == 0) break;
}
}
}
signed main(){
int n,m; cin>>n>>m;
ols(m);
for(int i=2;i<=m;i++) {
sum[i] = sum[i-1];
if(!vis[i]) sum[i] ++;
}
while(n --){
int l,r; cin>>l>>r;
if(l >= 1 && l <= m && r >= 1 && r <= m && l <= r)
cout<<(sum[r] - sum[l-1])<<endl;
else cout<<"Crossing the line"<<endl;
}
return 0;
}
P3912 (内存,性质N内大约有N/log(N)个质数)
Codeforces Round #686 (Div. 3) D 唯一分解定理。