今天没事做,我们来写个博客,混混等级!下面我们来解释质因子分解。
我们以求数的质因子的个数为例来讲解。
对于质因子分解最简单最纯粹的暴力我相信大家都会的。
int getnum(int x)
{
int ans=0;
for(int i=2;i*i<=x;i++)
{
while(x%i==0)
{
ans++;
x/=i;
}
}
return ans;
}
但是当处理的数据比较多,而且范围也比较大的时候显然这种方式就不再那么适合了。
既然我们是分解质因子,那么我们就可以先预处理出在范围内的所有素数,我们筛的时候用素数来筛选!
#define nn 1000010
bool vis[nn];
int k,p[nn],f[nn];
void init()
{
memset(vis,false,sizeof(vis));
vis[1]=true;
for(int i=2;i*2<=nn;i++)
if(!vis[i])
for(int j=i*i;j<=nn;j+=i)
vis[j]=true;
k=0;
for(int i=2;i<nn;i++)
if(!vis[i])
p[k++]=i;
}
int getnum(int x)
{
int ans=0;
for(int i=0;p[i]*p[i]<=x;i++)
{
while(x%p[i]==0)
{
ans++;
x/=p[i];
}
if(!vis[x])
{
ans++;
break;
}
}
return ans;
}
当然也可以用这种方式来预处理x小于nn的所有数的质因子个数。
#define nn 1000010
bool vis[nn];
int k,p[nn],f[nn];
void init()
{
memset(vis,false,sizeof(vis));
vis[1]=true;
for(int i=2;i*2<=nn;i++)
if(!vis[i])
for(int j=i*i;j<=nn;j+=i)
vis[j]=true;
k=0;
for(int i=2;i<nn;i++)
if(!vis[i])
p[k++]=i;
}
int getnum(int x)
{
int ans=0;
for(int i=0;p[i]*p[i]<=x;i++)
{
while(x%p[i]==0)
{
ans++;
x/=p[i];
}
if(!vis[x])
{
ans++;
break;
}
}
return ans;
}
void getsnum()
{
f[1]=0;
for(int i=2;i<nn;i++)
{
if(!vis[i]) f[i]=1;
else f[i]=getnum(i);
}
}
用这种方式来预处理小于nn的所有数的质因子个数的方式,我在本地跑用了大概0.125s。
上面的方式不仅可以求个数,也可以求出他的质因子是那些数。
下面我们来介绍一种很快算出质因子个数的姿势,但是只能算出个数而已,并不能算出是他的质因子是那些数。
它的思想基于素筛,复杂度和素筛的差不多。
#define nn 1000010
int f[nn];
void init()
{
memset(f,0,sizeof(f));
for(int i=2;i<nn;i++)
{
while(f[i]) i++;
f[i]=1;
for(int j=2;j*i<=nn;j++)
f[i*j]=f[j]+1;
}
}
就是这么简单,是不是没想到呀。
当然这种思想还可以求出它不同质因子的个数。处理方式相近,只是多了个if....else..而已
#define nn 1000010
int f[nn];
void init()
{
memset(f,0,sizeof(f));
for(int i=2;i<nn;i++)
{
while(f[i]!=0)
i++;
f[i]=1;
for(int j=2;j*i<=nn;j++)
{
if(j%i==0)
f[i*j]=f[j];
else
f[i*j]=f[j]+1;
}
}
}
如果有什么错误,还麻烦告诉我一下,我也好修改。