1.(对于一个足够大的整数N,不超过N的质数大约有N/lnN个,即每lnN个数中大约有1个质数.)
2.(约数总是成对出现的,如果M|N,则frac{N}{M}|N.)
- 试除法判定质数
bool is_prime(int n)
{
for(int i=2;i<=n/i;i++)
if(n%i==0)return flase;
return true;
}
- 筛质数:(给定整数N,求出1sim{N}之间所有的质数)
1.埃氏筛法
原理:
(任意整数X的倍数都不是质数.)
证明:
(对于2<=P<=N,如果P最后没有被筛掉,则P不是{2}sim{P-1}中任何一个数的倍数,)
(同理2sim{P-1}没有一个数是P的约数,根据质数定义,P是质数)
(复杂度O(loglog N))
int cnt,primes[N],st[N];
void f(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]=1;
/*
更快一些的写法
for(int j=i;j<=n/i;j++)等价于for(int j=i;j*i<=n;j++)在整数N范围内对质数的倍数进行标记
st[j*i]=1;*/
}
}
2.线性筛法
核心:
(每个合数只会被它的最小质因子筛掉,保证了时间复杂度是O(N))
(例如6在underline{埃氏筛}中会被2,3筛两次,underline{线性筛}中希望6(合数)只被2筛一次)
const int N=1e6+10;
int cnt,n,p[N],st[N];
cin>>n;
for(int i=2;i<=n;i++)
{
if(!st[i])p[cnt++]=i;
for(int j=0;j<cnt&&p[j]<=n/i;j++)
{
st[i*p[j]]=1;
if(i%p[j]==0)break;
}
}
cout<<cnt;
- 质因数分解:
1.算术基本定理
(任何一个大于1的正整数都能唯一分解为有限个质数的乘积:)
(
N=p_1^{c_1}p_2^{c_2}...p_m^{c_m}
\其中c_i都是正整数,p_i都是质数,且满足p_1<p_2<...<p_m.
)
2.重要定理
( 对于整数N,最多只有一个大于sqrt{N}的质因子 \ 反证法:如果N有多个大于sqrt{N},那么他们的乘积>N,矛盾 )
void f(int k)
{
for(int i=2;i<=k/i;i++)
{
int cnt=0;
if(k%i==0)//i一定是质数,因为有下面的while循环,对于K来说
{ //K的合数因子一定在扫描到这个合数之前就被质数从K中除掉了
//所以能整除K的一定不是合数。
cout<<i<<" ";
while(k%i==0)
{
cnt++;
k/=i;
}cout<<cnt<<endl;
}
}
if(k>1)
cout<<k<<" "<<"1"<<endl;
puts("");
}