找回密码
 欢迎注册
查看: 90179|回复: 112

[擂台] 计算百万位e

[复制链接]
发表于 2008-4-16 19:59:25 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
精华
e和$pi$一样,是数学分析中使用非常广泛的无理数之一。千百年来,有无数人投入到计算e和$pi$的计算工作中。相对于计算$pi$,计算e的算法较为简单,而且复杂度也低于计算$pi$。以Pifast 4.3为例,在我的电脑上(PIV2.6)计算100万位e值,仅需1.23秒,而计算100万$pi$则需要3.8秒。
   本文首先借助HugeCalc,探讨计算e的各种算法。当然大家也可以自己写个计算e的程序,比拼一下谁的程序很快,谁的算法更优。

  楼下使用的HugeCacl配置文件定义为:
[UserSetCPUID]
NumOfCores  =        1
SSE2Support =        1
CacheL1size =        8
CacheL2size =        512
CacheL3size =        0
Cacheburst  =        64

[ 本帖最后由 liangbch 于 2008-4-24 17:24 编辑 ]
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 20:02:02 | 显示全部楼层
我讨论一下最简单,最容易理解的算法。

  $e=1+ 1/1! + 1/2! + 1/3! + ... 1/n! $
  欲达到K位有效数字,需使得 $n!> 10^K$

算法描述
$ e=1+ 1/{1!} + 1/{2!} + 1/{3!} + ... 1/{n!} $
以n=5为例,我们将各项通分
  $e= 1/1$
  $+1/(1*2) $
  $+ 1/(1*2*3) $
  $+ 1/(1*2*3*4) $
  $+ 1/(1*2*3*4*5) $
  容易得到算法
  n=5,i=1, item=1, s=1;
  for (i=1;i<=5;i++)
  {
      item /=i ;
      s+=item;
  }
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-16 20:04:43 | 显示全部楼层
简单算法也不很慢吧?

不过是个O(n^2)算法
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 20:04:51 | 显示全部楼层
本帖给出使用HugeCalc库,使用楼上的算法,计算e的一个实现。该算法是一个O(n^2)的算法,在我的电脑上,计算10万位e需要7.61秒。
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <math.h>

  4. #include "../../HugeCalc/HugeCalc_API/CppAPI/Include/HugeCalc.h"        // 公共接口
  5. #include "../../HugeCalc/HugeCalc_API/CppAPI/Include/HugeInt.h"        // 10进制系统

  6. #pragma message( "automatic link to ../../HugeCalc/HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )
  7. #pragma comment( lib, "../../HugeCalc/HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )

  8. #define integer CHugeInt

  9. //返回计算d位有效数字所需的最大的n
  10. static UINT32 maxNForCalcE(int d)
  11. {
  12.         double f=d*log(10);
  13.         double r=0;
  14.         UINT32 i=0;
  15.         do
  16.         {
  17.                 i++;        r += log(i);
  18.         }while (r<f);
  19.         return i;
  20. }

  21. void calc_e_1(integer *p,int len)
  22. {
  23.         integer item;
  24.         integer r;
  25.         UINT32 n=maxNForCalcE(len);
  26.         UINT32 i;
  27.        
  28.         item=1L;
  29.         item.DecLShift(len); //增加有效数字

  30.         r=1L;
  31.         for (i=1;i<=n;i++)
  32.         {
  33.                 item /= i;
  34.                 r += item;
  35.         }
  36.         *p=r;
  37. }

  38. void calc_e1_main()
  39. {
  40.         int d,len;
  41.         integer e;
  42.         char *pBuff=NULL;
  43.         const char *pTmp;
  44.         char fileName[32];
  45.         FILE *fp=NULL;

  46.         printf("calculate e (simple version)\n");
  47.         printf("How many digital is needed?");
  48.         scanf("%d",&d);
  49.         len=(d+17)/9*9; //取9的倍数,可能稍微快一点

  50.         HugeCalc::EnableTimer( TRUE );
  51.         HugeCalc::ResetTimer();

  52.         calc_e_1(&e,len);

  53.         // 记录计算耗时
  54.         UINT32 u32Timer_Calc = HugeCalc::GetTimer( TIMER_UNIT_us );
  55.         printf("计算用时 %.6f 秒\n", (double)u32Timer_Calc/1000000.0);

  56.         //----------------------------------------
  57.         HugeCalc::EnableTimer( TRUE );
  58.         HugeCalc::ResetTimer();

  59.         pBuff=new char[e.GetDigits()+3];
  60.         if (pBuff==NULL)
  61.                 goto thisExit;

  62.         pTmp= e.GetStr(FS_NORMAL);
  63.         strcpy(pBuff+1,pTmp);
  64.        
  65.         pBuff[0]=pBuff[1];
  66.         pBuff[1]='.';        //插入小数点
  67.         pBuff[d+2]=0;        //去掉多余的数字

  68.         sprintf(fileName,"e1_%d.txt",d);
  69.         fp=fopen(fileName,"wb");
  70.         fwrite(pBuff,d+2,1,fp);
  71.         fclose(fp);        fp=NULL;

  72.         u32Timer_Calc = HugeCalc::GetTimer( TIMER_UNIT_us );
  73.         printf("输出到文件用时 %.6f 秒\n", (double)u32Timer_Calc/1000000.0);

  74. thisExit:
  75.         if (fp!=NULL)
  76.         {
  77.                 fclose(fp); fp=NULL;
  78.         }
  79.         if (pBuff!=NULL)
  80.         {
  81.                 delete[] pBuff;        pBuff=NULL;
  82.         }
  83. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 20:16:01 | 显示全部楼层
本帖将给出计算e的另一个算法,这个算法复杂度同4#,只是4楼主要使用大数除以单精度整数的算法,而该算法主要使用大数乘以单精度整数的算法。该算法比4#更快,在我的电脑上计算10万e值,需要5.88秒。
  
算法描述
$e=1+ 1/{1!} + 1/{2!} + 1/{3!} + ... 1/{n!}$
以n=5为例,我们将各项通分
$ e= {1xx2xx3xx4xx5}/{5!}+{2xx3xx4xx5}/{5!}+{3xx4xx5}/{5!}+{4xx5}/{5!}+5/{5!} + 1/{5!}$

调整各项顺序,并提取公分母得
$e=(1/{5!})xx ( 1+5+ 5xx4 + 5xx4xx3 + 5xx4xx3xx2 + 5xx4xx3xx2xx1)$
若 e 表示为分数p/q,则
$p = 1 +5 +5xx4 + 5xx4xx3 + 5xx4xx3xx2 + 5xx4xx3xx2xx1$
$q=5xx4xx3xx2 xx1$

容易得到算法
n=5
step1:q=1,p=1
step2:q *= n,p +=q ,n--
step3:如果n>0,转step2,否则转step4
step4:将分数 p/q化为小数,得到e
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 20:20:39 | 显示全部楼层
本帖给出使用HugeCalc,使用楼上算法计算e的一个实现。
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <math.h>

  4. #include "../../HugeCalc/HugeCalc_API/CppAPI/Include/HugeCalc.h"        // 公共接口
  5. #include "../../HugeCalc/HugeCalc_API/CppAPI/Include/HugeInt.h"        // 10进制系统

  6. #pragma message( "automatic link to ../../HugeCalc/HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )
  7. #pragma comment( lib, "../../HugeCalc/HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )


  8. #define integer CHugeInt

  9. //计算e的稍复杂的版本,用到大数加法,以及大数乘法和大数除法
  10. //该程序快于第一个版本,特别是要求精度较低时,优势更为明显。

  11. //欲达到n位有效数字,需使得 n!> 10^n
  12. //返回计算d位有效数字所需的最大的n
  13. static UINT32 maxNForCalcE(int d)
  14. {
  15.         double f=d*log(10);
  16.         double r=0;
  17.         UINT32 i=0;
  18.         do
  19.         {
  20.                 i++;        r += log(i);
  21.         }while (r<f);
  22.         return i;
  23. }

  24. void calc_e_2(integer *r,int len)
  25. {
  26.         integer p,q;
  27.         UINT32 n=maxNForCalcE(len);
  28.        
  29.         p=1; q=1;
  30.         do
  31.         {
  32.                 q*=n;
  33.                 p+=q;
  34.                 n--;
  35.         }while (n>0);
  36.        
  37.         p.DecLShift( q.GetDigits()-1); //增加有效数字
  38.         *r = p / q;
  39. }

  40. void calc_e2_main()
  41. {
  42.         int d,len;
  43.         integer e;
  44.         char *pBuff=NULL;
  45.         const char *pTmp;
  46.         char fileName[32];
  47.         FILE *fp=NULL;

  48.         printf("calculate e (simple version2)\n");
  49.         printf("How many digital is needed?");
  50.         scanf("%d",&d);
  51.         len=(d+17)/9*9; //取9的倍数,可能稍微快一点

  52.         HugeCalc::EnableTimer( TRUE );
  53.         HugeCalc::ResetTimer();

  54.         calc_e_2(&e,len);

  55.         // 记录计算耗时
  56.         UINT32 u32Timer_Calc = HugeCalc::GetTimer( TIMER_UNIT_us );
  57.         printf("计算用时 %.6f 秒\n", (double)u32Timer_Calc/1000000.0);

  58.         //----------------------------------------
  59.         HugeCalc::EnableTimer( TRUE );
  60.         HugeCalc::ResetTimer();

  61.         pBuff=new char[e.GetDigits()+3];
  62.         if (pBuff==NULL)
  63.                 goto thisExit;

  64.         pTmp= e.GetStr(FS_NORMAL);
  65.         strcpy(pBuff+1,pTmp);
  66.        
  67.         pBuff[0]=pBuff[1];
  68.         pBuff[1]='.';        //插入小数点
  69.         pBuff[d+2]=0;        //去掉多余的数字

  70.         sprintf(fileName,"e2_%d.txt",d);
  71.        
  72.         fp=fopen(fileName,"wb");
  73.         fwrite(pBuff,d+2,1,fp);
  74.         fclose(fp);        fp=NULL;

  75.         u32Timer_Calc = HugeCalc::GetTimer( TIMER_UNIT_us );
  76.         printf("输出到文件用时 %.6f 秒\n", (double)u32Timer_Calc/1000000.0);

  77. thisExit:
  78.         if (fp!=NULL)
  79.         {
  80.                 fclose(fp); fp=NULL;
  81.         }
  82.         if (pBuff!=NULL)
  83.         {
  84.                 delete[] pBuff;        pBuff=NULL;
  85.         }
  86. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 20:35:28 | 显示全部楼层
本帖将给出一个快速的算法,这个算法能够充分利用大数乘法,计算速度比前两个算法快的多(在PIV2.6上,计算10万位e需0.66秒,计算100万位e需要8.35秒)

算法详述:
$e=1+1/{1!} + 1/{2!} + 1/{3!}+ 1/{4!} + ... 1/{N!}$ (一)
现在我们将讨论如何化解
$ 1/{1!} + 1/{2!} + 1/{3!}+ 1/{4!} + ... 1/{N!}$ (二)
   为$p/q$
以计算 $ 1/{1!} + 1/{2!} + 1/{3!} + 1/{4!} +1/{5!} + 1/{6!} + 1/{7!} + 1/{8!}$ 为例

将这个多项式分成2部分得
  第一部分为:$( 1/{0!}) xx( 1/1 + 1/{1xx2} + 1/{1xx2xx3}+1/{1xx2xx3xx4})$
  第二部分为:$1/{4!}(1/5+1/{5xx6}+1/{5xx6xx7}+1/{5xx6xx7xx8})$
  暂不考虑系数$1/{0!}$和$1/{4!}$,则问题转化为求
    $1/n+ 1/{nxx(n+1)}+1/{n(n+1)(n+2)} ...+1/{n(n+1)(n+2)...m}$ (三)
   的形式。易看出,若这个多项的的计算结果为$ p/q $,则 $q=nxx(n+1)xx(n+2)xx...(m) $
  
  当m-n较小时,我们可以按照calc_Frac_Sum中的方法直接计算,
   
  当m-n较大时,我们可以将这个多项式再分成2段,
   一段为从n 到 (n+m)/2,另一端为一段为从(n+m)/2+1 到 m
  令r=(n+m)/2、s=(n+m)/2+1
  为了计算(三),我们先分别计算
  $1/n + 1/{(n(n+1))} + ...1/{(n(n+1)...r)}$ (四)
    $1/s + 1/{(s(s+1))} + ...1/{(s(s+1)...m)} $(五)
  
  令  (三)的计算结果为$p/q$,
      (四)的计算结果为${p1}/{q1}$,
      (五)的计算结果为${p2}/{q2}$,
   
   则:$1/n+ 1/{nxx(n+1)}+1/{n(n+1)(n+2)}+...+1/{n(n+1)(n+2)...r}$
    $+1/{n(n+1)(n+2)...s} + ... + 1/{n(n+1)(n+2)...m}$
    $= p/q$
    $= {p1}/{q1} + (1/{nxx(n+1)xx(n+2)xx..r}) xx {p2}/{q2}$
    $= {p1}/{q1} + 1/{q1} xx {p2}/{q2}$
    $= {p1xxq2}/{q1xxq2} + {p2}/{q1xxq2}$
    $= {p1xxq2+p2}/{q1xxq2}$
  所以:$p=p1xxq2+p2, q=q1xxq2$
  
下面,我们以$(1/5+1/{5xx6} + 1/{5xx6xx7} + 1/{5xx6xx7xx8})$ 说明计算过程:
$ p/q= 1/5 + 1/{5xx6} + 1/{5xx6xx7} + 1/{5xx6xx7xx8}$
$= (1/5 + 1/{5xx6}) + (1/{5xx6xx7} + 1/{5xx6xx7xx8})$
$= ((6+1)/(5xx6)) + 1/(5xx6) xx ( 1/7 + 1/{7xx8} )$
$= ((6+1)/(5xx6)) + 1/(5xx6) xx ( {8+1}/{7xx8} ) $
$= (7/30) + 1/(30) xx ( 9/56)$
$= (7 xx 56 + 9 )/(30xx56)$
  按此法计算,使用递归方式,所有的多项式终将合并,这时n=1,m=N,因此(二)将变为(三)
  则有e
$=1+1/{1!}+1/{2!}+1/{3!} + ...1/{N!}$
$=1+p/q$
$ =(p+q)/q$
  最后我们作一次除法,将分数(p+q)/q化为小数即可
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-16 20:38:13 | 显示全部楼层
看不懂哦
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 21:31:16 | 显示全部楼层
本帖给出使用HugeCalc,使用7#楼算法计算e的一个实现,使用该程序,在PIV2.6上,计算10万位e需0.412秒,计算100万位e需要5.06秒。
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <math.h>

  4. #include "../../../HugeCalc_API/CppAPI/Include/HugeCalc.h"        // 公共接口
  5. #include "../../../HugeCalc_API/CppAPI/Include/HugeInt.h"        // 10进制系统

  6. #pragma message( "automatic link to ../../../HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )
  7. #pragma comment( lib, "../../../HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )


  8. #define integer CHugeInt
  9. #define USE_HUGE_CALC_DIV

  10. #if 0
  11. #        define MODIFIED_BY_GxQ
  12. #endif

  13. #define MIN_SPLIT 32
  14. static DWORD g_divTime=0;

  15. // 计算e的一个快速的版本,采用2分法,尽量使用以及大数乘法,
  16. // 收尾阶段采用大数除法


  17. //欲达到n位有效数字,需使得 n!> 10^n
  18. //返回计算d位有效数字所需的最大的n

  19. static UINT32 maxNForCalcE(int d)
  20. {
  21.         double f=d*log(10);
  22.         double r=0;
  23.         UINT32 i=0;
  24.         //loop untill log(n!)>log(10^d)
  25.         do
  26.         {
  27.                 i++; r += log(i);
  28.         }while (r<f);
  29.         return i;
  30. }

  31. // calc 1/n1 + 1/(n1*(n1+1)) + 1/(n1*(n1+1)+(n1+2))+ 1/(n1*(n1+1)+(n1+2)+...m)
  32. // 计算结果为 p/q
  33. // for example:

  34. // 1/6 + 1/6*7 + 1/6*7*8 + 1/6*7*8*9
  35. // = 7*8*9/6*7*8*9 + 8*9/6*7*8*9 + 9/6*7*8*9 + 1/ 6*7*8*9
  36. // calculate
  37. //    q=6*7*8*9, p=1 + 9+ 8*9 + 7*8*9
  38. // steps:
  39. // step1: p=1, q=1;
  40. // step2: q*=9, p+=q   ,  q=9,     q=1+9
  41. // step3: q*=8, p+=q   ,  q=9*8,   q=1+8*9
  42. // step4: q*=7, p+=q   ,  q=9*8*7, q=1+ 8*9 + 7*8*9
  43. // step5: q*=6
  44. static void calc_Frac_Sum(UINT32 n1,UINT32 n2, integer &p,integer &q)
  45. {
  46.         p=(UINT32)1;
  47.         q=(UINT32)1;
  48.         for ( UINT32 i=n2;i>n1;i--)
  49.         {
  50.                 q*=i;
  51.                 p+=q;
  52.         }
  53.         q*=i;
  54. }

  55. #ifndef MODIFIED_BY_GxQ
  56. void splitCalc(UINT32 n1,UINT32 n2, integer &p,integer &q)
  57. {
  58.         if (n2-n1<=MIN_SPLIT)
  59.         {
  60.                 calc_Frac_Sum(n1,n2,p,q);
  61.         }
  62.         else
  63.         {
  64.                 integer p1,q1,p2,q2;
  65.                 splitCalc( n1, (n1+n2)/2,   p1,q1);
  66.                 splitCalc( (n1+n2+2)/2 ,n2, p2,q2);
  67.                 p=p1*q2 + p2;
  68.                 q=q1*q2;
  69.         }
  70. }
  71. #else
  72. integer tmp;
  73. void splitCalc(UINT32 n1,UINT32 n2, integer &p,integer &q)
  74. {
  75.         if (n2-n1<=MIN_SPLIT)
  76.         {
  77.                 calc_Frac_Sum(n1,n2,p,q);
  78.         }
  79.         else
  80.         {
  81.                 integer q1,p2;
  82.                 splitCalc( n1, (n1+n2)/2,   p, q1);
  83.                 splitCalc( (n1+n2+2)/2 ,n2, p2,q );

  84.                 // ( p *= q ) += p2;
  85.                 tmp.Swap( p );
  86.                 p.Mul( tmp, q ) += p2;

  87.                 // q *= q1;
  88.                 tmp.Swap( q );
  89.                 q.Mul( tmp, q1 );
  90.         }
  91. }
  92. #endif

  93. void calc_e_3(integer *r, int len )
  94. {
  95.         UINT32 n;
  96.         int shift;
  97.         integer p,q;

  98.         n= maxNForCalcE(len)+2;
  99.         splitCalc(1,n,p,q);  // p/q= 1/1!+1/2!+1/3!+1/4!+...

  100.         p+=q;  // p/q +=1     // e= p/q= 1 + 1/1!+1/2!+1/3!+1/4!+...
  101.         shift=(len+8)/9*9;  //get upbounds get times of 9
  102.         p.DecLShift(shift); //增加有效数字

  103.         g_divTime=GetTickCount();
  104. #ifdef USE_HUGE_CALC_DIV
  105. #ifndef MODIFIED_BY_GxQ
  106.         p=p /q;
  107. #else
  108.         p /= q;
  109. #endif
  110. #else
  111.         {
  112.                 void inverse( const integer *s, integer *pResult,int len);
  113.                 integer t;
  114.                 inverse(&q,&t,len);
  115.                 p *=t;
  116.         }
  117. #endif
  118.         g_divTime=GetTickCount()-g_divTime;
  119.         *r=p;
  120. }

  121. void calc_e3_main()
  122. {
  123.         int len;
  124.         integer e;
  125.         char *pBuff=NULL;
  126.         const char *pTmp;
  127.         char fileName[32];
  128.         FILE *fp=NULL;

  129.         printf("calculate e (fast version1)\n");
  130. #ifdef MODIFIED_BY_GxQ
  131.         printf("defined 'MODIFIED_BY_GxQ'\n");
  132. #endif
  133.         while (true)
  134.         {
  135.                 printf("How many digital is needed(0 will exit)?");
  136.                 scanf("%d",&len);
  137.                 if (len==0)
  138.                         break;

  139.                 HugeCalc::EnableTimer( TRUE );
  140.                 HugeCalc::ResetTimer();

  141.                 calc_e_3(&e,len);

  142.                 // 记录计算耗时
  143.                 UINT32 u32Timer_Calc = HugeCalc::GetTimer( TIMER_UNIT_us );
  144.                 printf("计算用时 %.6f 秒\n", (double)u32Timer_Calc/1000000.0);
  145.                 if (g_divTime>=2)
  146.                 {
  147.                         printf("其中除法用时 %f秒\n", (double)g_divTime/1000.00);
  148.                 }
  149.                 //----------------------------------------
  150.                 HugeCalc::EnableTimer( TRUE );
  151.                 HugeCalc::ResetTimer();

  152.                 pBuff=new char[e.GetDigits()+3];
  153.                 if (pBuff==NULL)
  154.                         goto thisExit;

  155.                 pTmp= e.GetStr(FS_NORMAL);
  156.                 strcpy(pBuff+1,pTmp);

  157.                 pBuff[0]=pBuff[1];
  158.                 pBuff[1]='.'; //插入小数点
  159.                 pBuff[len+2]=0; //去掉多余的数字

  160.                 sprintf(fileName,"e3_%d.txt",len);
  161.                 FILE *fp=fopen(fileName,"wb");
  162.                 fwrite(pBuff,len+2,1,fp);
  163.                 fclose(fp); fp=NULL;
  164.                 delete[] pBuff; pBuff=NULL;

  165.                 u32Timer_Calc = HugeCalc::GetTimer( TIMER_UNIT_us );
  166.                 printf("输出到文件用时 %.6f 秒\n", (double)u32Timer_Calc/1000000.0);
  167.         }

  168. thisExit:
  169.         if (fp!=NULL)
  170.         {
  171.                 fclose(fp); fp=NULL;
  172.         }
  173.         if (pBuff!=NULL)
  174.         {
  175.                 delete[] pBuff; pBuff=NULL;
  176.         }
  177. }
复制代码

[ 本帖最后由 liangbch 于 2008-4-17 14:34 编辑 ]
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-16 21:37:11 | 显示全部楼层


我想
我想
是不是有更精彩更复杂的算法

比如类似阶乘的?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-3-19 16:12 , Processed in 0.046247 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表