进阶实验2-3.4 素因子分解
给定某个正整数N,求其素因子分解结果,即给出其因式分解表达式 $N=p1^{k_1}\cdotp2^{k_2}···pm^{k_m}$。
输入格式:
输入long int范围内的正整数 N。
输出格式:
输入第一行给出 3 个不超过 1000 的正整数:M(堆栈最大容量)、N(入栈元素个数)、K(待检查的出栈序列个数)。最后K行,每行给出N个数字的出栈序列。所有同行数字以空格间隔。
输入样例:1323
输出样例1:
1323=3^3*7^2
算法分析
标程是递归去求素因子。即设输入为 $n$ , $F(n)=prime(i)*F(n/prime(i))$ 。
这样子感觉效率有点慢。我的做法是欧拉素数先打个素数表,然后线性扫一遍素数表,每次 $n$ 循环除以最小的素数,除不清的时候 continue
就好了。
举个例子。
设 $n=12$ 。通过欧拉法在线性的时间复杂度内筛出素数向量 $prime=[2,3,5,7,...]$ ,初始下标为 $0$,结果向量 $ans$,第 $i$ 位代表 $prime[i]$ 的指数。
那么从 $prime[i]$ 开始,每次去除以 $prime(i)$:
第一次:$n=n/prime[0]==12/2==6, ans[i]++==1$ 。即 $2$ 作为 $12$的质因子,指数目前为 $1$ 。
第二次:$n=n/prime[0]==6/2==3, ans[i]++==2$ 。即 $2$ 作为 $12$的质因子,指数目前为 $2$ 。
第三次:$n=n/prime[0]==3/2,无法整除, 即 $2$ 的最终指数为 $2$ 。
接下来递推去处理 $prime[i+1]$ 就好。
最后结果向量 $ans$ 即为所求。
如果不知道欧拉素数法的可以百度一下。
代码
#include <stdio.h>
#define PRIME_COUNT 350 /* 素数最大个数 */
#define MAX_PRIME 2000 /* 打表找小于MAX_PRIME的素数 */
int main()
{
long long int n;
short f[MAX_PRIME] = {0}; /* 素数标记数组 */
int prime[PRIME_COUNT] = {0}, cnt = 0; /* 素数数组,素数个数 */
for(int i=2; i<MAX_PRIME; i++){ /* 欧拉素数打表,线性复杂度筛出小于MAX_PRIME的素数 */
if(!f[i]) prime[cnt++] = i;
for(int j=0; j<cnt; j++){
if(i*prime[j] >= MAX_PRIME) break;
f[i*prime[j]]++;
if(i%prime[j] == 0) break;
}
}
scanf("%lld", &n);
if(n==1){
printf("1=1\n");
return 0;
}
printf("%d=", n);
int isFirst = 1; /* 从小到大遍历素数数组寻找n的素因子 */
for(int i=0; i<cnt; i++){
long long int index = 0; /* 指数 */
if(n==1) break;
while(n%prime[i] == 0){
n = n / prime[i];
index++;
}
if(isFirst && index!=0){
if(index>1) printf("%d^%d", prime[i], index);
else printf("%d", prime[i]);
isFirst = 0;
}else if(isFirst==0 && index!=0){
if(index>1) printf("*%d^%d", prime[i], index);
else printf("*%d", prime[i]);
}
}
printf("\n");
return 0;
}
小结
希望考研也有这么简单。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。