逝者如斯,不舍昼夜

尘世中一个迷途小书童,读书太少,想得太多
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

算法篇——因子和阶乘

Posted on 2015-08-30 22:03  SteveWang  阅读(1664)  评论(0编辑  收藏  举报

 

  来源:《算法竞赛入门经典》例题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("\n");

    }
    return 0;
}