来源:《算法竞赛入门经典》例题5.4.2
题目:输入正整数n(2≤n≤100),把阶乘n!=1*2*3*...*n分解成素因子相乘的形式,从小到大输出各个素数(2、3、5...)的指数。例如,5! 表示为 3 1 1(5!=23*31*51=120),程序忽略比最大素因子更大的素数(否则末尾会有无穷多个0)
样例输入:
5
53
样例输出:
5! = 3 1 1
53! = 49 23 12 8 4 4 3 2 2 1 1 1 1 1 1 1
分析:
注意到n<=100,所以素因子也一定不会超过100(可以用反证法证明如果存在大于100的素因子,这个素因子在等式上无法消去,等式不成立)。
我们首先构造一张素数表,然后用阶乘的每个因子(从小到大)与素数表中的素数取模,能整除就证明该素数是素因子,并记录每一个素数的指数。因为am * an = am+n,所以我们需要把素因子对应的指数做累加 。用一个数组p来保存对应的各个素数的指数,并标记最大的那个素因子的下标为maxp,最后循环输出到最大素因子的指数即可。
源码:
#include<stdio.h> #include<string.h> int is_prime(int n) { int i; for(i=2;i*i<=n;i++) if(n%i==0) return 0; return 1; } int main() { int n,m,i,j,prime[100],p[100],maxp,count=0;//primer为素数表,p为素数表中各个素数对应的指数 //count为素数表中素数的数量,maxp为最后可以输出的最大素因子对应于p的下标 for(i=2;i<=100;i++) //构造素数素数表,素数因子一定不超过100 if(is_prime(i)) prime[count++]=i; while(scanf("%d",&n)==1) { printf("%d! =",n); memset(p,0,sizeof(p)); //各素数对应的指数置0 maxp=0; //最大素因子索引置0 for(i=1;i<=n;i++) { m=i; //阶乘的每个因子都循环除以(取模)素数表中的素数 for(j=0;j<count;j++) while (m%prime[j]==0) //能整除证明是素因子 { m/=prime[j]; p[j]++; //因子指数加1 if(j>maxp) maxp=j; //更新最大素因子下标 } } for(i=0;i<=maxp;i++) //忽略比最大素因子更大的素数 printf(" %d",p[i]); printf(" "); } return 0; }