第一题:
思路:
这个题,虽说看着恶心,但是,这是一个组合类型的题目,相当于一个素数筛法和一个取模运算的综合题。至于计算质因数,只需要一直取模一直取模就可以了,只不过这个代码要和数位拆解的代码进行相应的区分。
代码如下:
#include<stdio.h>
bool mark[100001];
int prime[100001];
int primeSize;
void init(){
for(int i=0;i<100001;i++){
mark[i]=false;
}
primeSize=0;
for(int i=2;i<100001;i++){
if(mark[i]==true)continue;
prime[primeSize++]=i;
if(i>=1000)continue;//对于这个,我个人感觉可加可不加,,
//因为这个语句相对于下面的只是少了一个加减乘除运算的步骤,至于这个时间消耗,可能不是很大吧。
for(int j=i*i;j<100001;j+=i){
mark[j]=true;
}
}
}//素数筛法模板函数
int main(){
init();
int n;
while(scanf("%d",&n)!=EOF){
int ansPrime[30];//记录,结果的素因数
int ansSize=0;//记录结果的个数
int ansNum[30];//记录结果的幂次
for(int i=0;i<primeSize;i++){//对于所有的素数,依次判断是否为因数
if(n%prime[i]==0){
ansPrime[ansSize]=prime[i];
ansNum[ansSize]=0;//如果可以,进行相应的初始化准备工作
while(n%prime[i]==0){
ansNum[ansSize]++;
n/=prime[i];
}
ansSize++;
if(n==1)break;//当n变为1的时候说明素因数已经分解完毕了。
}
}
if(n!=1){//若此时的n不为1,则一定存在一个大于100000的因数,并且这个因数一定为素因数
ansPrime[ansSize]=n;
ansNum[ansSize++]=1;
}
int ans=0;
for(int i=0;i<ansSize;i++){
ans+=ansNum[i];
}
printf("%d\n",ans);
}
return 0;
}
难点:
对于这个,难点可能有三个:
- 为什么只用100000以内的素因数
- 为什么当n=1时,余下的那个数一定是一个素因数。
- 为什么分解素因数要从小开始,难道答案就一定唯一吗?
答:
首先回答第三个问题,这个答案一定是唯一的,证明(个人理解):
假设答案不唯一,则对于数 n 存在一个结果 : x1*x2*x3=y1*y2*y3,其中x与y不完全相同
因为每个数都是素数,并且是整数,只存在1和其本身为其因数。
假设x3与y不同,这时将x3除过去,如下 x1*x2=y1*y2*y3 / x3 此时x1*x2必为一个整数
那么右边也必然是一个整数,也就是说x3必然被约掉了,即y1*y2*y3这个因式中必然存在因子可以约掉x3,
但是他们都是素数,对于素数来说,只存在1和其本身为其因数,所以原则上他们数不能约分的。
所以这就与假设所矛盾,即上面这种结果根本就不存在,即答案必然唯一。
其次是第一个问题和第二个问题:
现在n可分解素因数,对于其素因数来说,如果存在大于sqrt(n)的因数,只能有一个,如果有俩,就大于n了。
所以我们只需要遍历小于sqrt(n)的素因数,剩下的那一个必然为大于sqrt(n)的,且必然为素因数。
第二题: