2006
12-27

本题采用链表(n<int)占用空间小但在处理大的数时时间较长。望那位高手指点,用较短的时间又处理较大的数。


联系我:许夏,gordon772@yahoo.com.cn 多谢!


程序如下:


#include<stdio.h>
#include<malloc.h>
struct number
{  int data;
   struct number *next;
}num;
struct number *create(int n)           /*从个位到高位循环*/
{  int i=1,t,flag=0;
   struct number *head,*r,*p,*s;
 head=(struct number *)malloc(sizeof(num)) ;
   head->next=NULL;
   s=(struct number *)malloc(sizeof(num));
   if(head->next==NULL)
   {   head->next=s;head->data=0;   }
   head->next->data=1;
   s->next=NULL;
   while(i<=n)              /*先乘后加*/
 { r=head->next;
   while(r!=NULL)
  { t=r->data*=i;   flag=0;
    if(t>9&&r->next==NULL)
   {  r->data=t%10;  t/=10;
      s=(struct number *)malloc(sizeof(num));
      s->data=t%10;  s->next=NULL;
      r->next=s;     r=s;
      t/=10;
      while(t>0)
      {  s=(struct number *)malloc(sizeof(num));
      s->data=t%10;    s->next=NULL;
      r->next=s;       r=s;
      t/=10;
      }
   }
   r=r->next;
   }
   p=head->next;
   while(p!=NULL)
   {
    t=p->data;
    if(t>9)
    {
      p->data=t%10;
      t/=10;
      p=p->next;     /*注意和的[··]关系*/
      p->data+=t;
      if(p->data>9)
      {  flag=p->data;
      p->data=flag%10;
      flag/=10;
      p->next->data+=flag;        /*连续进两位以上*/
      }
    }
    while(t>9&&p->next==NULL)
    {   if(t>0)
     {   p->data=t%10;    t/=10;
      s=(struct number *)malloc(sizeof(num));
      s->data=t%10;    s->next=NULL;
      p->next=s;       p=s;
      t/=10;
     }
    }
    p=p->next;
   }
   i++;
   }
   head=head->next;    /*[··]*/
   return head;
}
void disp(struct number *head)           /*输处联表*/
{  while(head!=NULL)
   {   printf(“%d”,head->data);
    head=head->next;
   }
   printf(“\n”);
}
struct number *move(struct number *h)        /*链表倒置*/
{ struct number *p,*q,*r=h;
  q=h->next;p=h;
  while(q!=NULL)
  { r=q->next;   q->next=p;
 p=q;         q=r;
  }
  h->next=NULL;
  h=p;
  return(h);
}
main()
{  int d;
   struct number *h,*p;
   printf(“Please input the N!  number :”);
   scanf(“%d”,&d);
   if(d==0)
   {  printf(“\nThe Result is :  %d\n”,d+1);
   return 0;
   }
   h=create(d);
   h=move(h);
   printf(“\nThe Result is :  “);
   disp(h);
   printf(“\n”);
}


n!的求解》有 3 条评论

  1. ZhuBin 说:

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #define Pi 3.14159265358979323846L

    //可以计算1000!
    short mul(short a[], short d, short x)
    {
     long i, y = 0;
     for (i = 0; i < d; i++)
     {
      y += a[i]*(long)x;
      a[i] = (short)(y % 10000);
      y /= 10000;
     }
     a[d] = (short)y;
     return d + y?1:0;
    }

    void main()
    {
     long s;
     short *a, i, j, n, ws = 1;
     printf(“N=”);
     scanf(“%d”, &n);

     s = (long)((log(2 *Pi * n) / 2+n *(log(n) – 1)) / log(10) + 1);
     a = (short*)malloc((s / 4+2) *sizeof(short));
     *a = 1;

     for (i = 2; i <= n; i++)
     {
      ws = mul(a, ws, i);
     }

     printf(“%d!=%d”, n, a[ws - 1]);
     for (j = ws – 2; j >= 0; j–)
     {
      printf(“%04d”, a[j]);
     }
     printf(“\n”);
     free(a);
    }

  2. xiangqianxu 说:

    //考虑大数的问题,要用数组来存储数据

    int factorial(int n)

    {

         int a[1000]; //确保保存最终运算结果的数组足够大

         int carry;//进位

         int digit = 1;//位数

         a[0] = 1;//将结果先初始化为1

         int temp;//阶乘的任一元素与临时结果的某位的乘积结果

         int i,j;

         for(i = 2; i <= n; ++i)//开始阶乘,阶乘元素从2开始依次“登场”

         {//按最基本的乘法运算思想来考虑,将临时结果的每位与阶乘元素相乘   

             for(j = 1, carry = 0; j <= digit; ++j)     

             {

    temp = a[j-1] * i + carry;//相应阶乘中的一项与当前所得临时结果的某位相乘(加上进位)       

                  a[j-1] = temp % 10;//更新临时结果的位上信息  

                  carry = temp / 10; //看是否有进位

             }

             while(carry)//如果有进位

             {

                  a[++digit-1] = carry % 10;//新加一位,添加信息。位数增1  

                  carry /= 10;//看还能不能进位

             }

         }

         printf(“结果是:\n%d ! = “,n);//显示结果

         for(i = digit; i >=1; –i)

         {

             printf(“%d”,a[i-1]);

         }

         return 0;

    }

  3. hiroki 说:

    有好的求解方法啊

留下一个回复