找回密码
 欢迎注册
楼主: shingyuan

[求助] 求因子个数的问题

[复制链接]
发表于 2011-11-9 21:20:43 | 显示全部楼层
在吃晚饭的时候,回顾了一遍我写的代码,发现一个大bug,待会儿给出修改后的代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-11-9 21:56:29 | 显示全部楼层
下面是修正后的代码,速度基本和3楼同
  1. // URL: http://bbs.emath.ac.cn/redirect.php?tid=3786&goto=lastpost#lastpost
  2. #include <windows.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <math.h>
  6. typedef unsigned long DWORD;
  7. typedef unsigned char BYTE;
  8. // 一定范围内质数的个数
  9. // 10 4
  10. // 100 25
  11. // 1,000 168
  12. // 10,000 1,229
  13. // 100,000 9,592
  14. // 1,000,000 78,498
  15. // 10,000,000 664,579
  16. // 100,000,000 5,761,455
  17. // 1,000,000,000 50,847,534
  18. // 10,000,000,000 455,052,511
  19. // 100,000,000,000 4,118,054,813
  20. // 1,000,000,000,000 37,607,912,018
  21. // 10,000,000,000,000 346,065,536,839
  22. // 100,000,000,000,000 3,204,941,750,802
  23. // 1,000,000,000,000,000 29,844,570,422,669
  24. // 10,000,000,000,000,000 279,238,341,033,925
  25. // 100,000,000,000,000,000 2,623,557,157,654,233
  26. // 1,000,000,000,000,000,000 24,739,954,287,740,860
  27. // 估计x 范围内的质数的个数, 欧拉公式 pi(x)=x /( ln(x));
  28. // 经过测试,
  29. // 在1-1百万之间,相邻2个质数的最大差为114,这两个质数分别为492113,492227
  30. // 在1-1千万之间,相邻2个质数的最大差为154,这两个质数分别为4652353,4652507
  31. // 在1-3千万之间,相邻2个质数的最大差为210,这两个质数分别为20831323,20831533
  32. // 在1-1亿之间, 相邻2个质数的最大差为220,这两个质数分别为47326693,47326913
  33. static LARGE_INTEGER freq;
  34. static BOOL initFreq()
  35. {
  36. BOOL ret;
  37. if ( !QueryPerformanceFrequency( &freq) )
  38. { ret=FALSE; }
  39. else
  40. { ret=TRUE; }
  41. return ret;
  42. }
  43. double currTime() //使用高精度计时器
  44. {
  45. LARGE_INTEGER performanceCount;
  46. BOOL result;
  47. double time=0.0;
  48. BOOL bRet=TRUE;
  49. if (freq.QuadPart==0)
  50. {
  51. bRet=initFreq();
  52. }
  53. if (bRet)
  54. {
  55. result=QueryPerformanceCounter( &performanceCount );
  56. time= performanceCount.HighPart * 4294967296.0 + performanceCount.LowPart;
  57. time=time / ( freq.HighPart * 4294967296.0 + freq.LowPart);
  58. }
  59. return time;
  60. }
  61. #define MAX_PRIME 302
  62. struct FAC_ARR_ST
  63. {
  64. int fc;
  65. struct
  66. {
  67. DWORD p;
  68. int e;
  69. }arr[10]; //2^32以内的数最大9个素因子
  70. };
  71. struct FAC_ARR_ST g_facTab;
  72. void add_to_facTab(DWORD p)
  73. {
  74. int i;
  75. int bfind=0;
  76. for (i=0;i<g_facTab.fc;i++)
  77. {
  78. if ( g_facTab.arr[ i ].p==p)
  79. {
  80. g_facTab.arr[ i ].e++;
  81. bfind=1;
  82. break;
  83. }
  84. }
  85. if ( !bfind )
  86. {
  87. g_facTab.arr[g_facTab.fc].p=p;
  88. g_facTab.arr[g_facTab.fc].e=1;
  89. g_facTab.fc++;
  90. }
  91. }
  92. //**********************************************
  93. // n 不能大于L2 cache,否则效能很低
  94. DWORD Sift32(DWORD n,DWORD *primeTab)
  95. // 对0到n 之间(不包括n)的数进行筛选,返回质数的个数
  96. //**********************************************
  97. {
  98. BYTE *pBuff= new BYTE[n];
  99. if (pBuff==NULL)
  100. return 0;
  101. DWORD i,sqrt_n,p;
  102. DWORD pn;
  103. //----------------------------
  104. sqrt_n=(DWORD)(sqrt((double)n)+1);
  105. while (sqrt_n * sqrt_n >=n)
  106. sqrt_n--;
  107. memset(pBuff,1,n*sizeof(BYTE));
  108. *pBuff=0;
  109. *(pBuff+1)=0; //1不是质数
  110. *(pBuff+2)=1; //2是质数
  111. for ( i=4;i<n;i+=2) //筛去2的倍数,不包括2
  112. *(pBuff+i)=0;
  113. for (i=3;i<=sqrt_n;) //i 是质数
  114. {
  115. for (p=i*i;p<n; p+=2*i)
  116. *(pBuff+p)=0; //筛去i 的奇数倍
  117. i+=2;
  118. while ( *(pBuff+i)==0 )
  119. i++; //前进到下一个质数
  120. }
  121. pn=0; //素数个数
  122. if ( primeTab==NULL)
  123. {
  124. for (i=2;i<n;i++)
  125. {
  126. if (pBuff[ i ])
  127. pn++;
  128. }
  129. }
  130. else
  131. {
  132. for (i=2;i<n;i++)
  133. {
  134. if (pBuff[ i ])
  135. primeTab[pn++]=i;
  136. }
  137. }
  138. delete[] pBuff;
  139. return pn;
  140. }
  141. void check_all(DWORD max_n)
  142. {
  143. DWORD *primeTab=NULL;
  144. DWORD primeCount;
  145. DWORD i,j,k;
  146. int f_c; //因子数
  147. int max_fc; //最大因子数
  148. //创建一个素数表
  149. primeCount=Sift32(MAX_PRIME,NULL); //得到MAX_PRIME以内的素数个数
  150. primeTab=(DWORD *)malloc(sizeof(DWORD)* (primeCount+1));
  151. Sift32(MAX_PRIME,primeTab);
  152. primeTab[primeCount]=2147483647; //设置一个栅栏
  153. for (max_fc=0,i=2;i<=max_n;i++)
  154. {
  155. DWORD na[2];
  156. if (i & 1) //i是奇数
  157. { na[0]=i; na[1]=(i+1)/2;}
  158. else
  159. { na[0]=i/2; na[1]=i+1; }
  160. for (g_facTab.fc=0,j=0;j<2;j++)
  161. {
  162. DWORD n,r;
  163. r=n=na[j];
  164. // primeTab[primeCount]=2147483647,保证循环能够终止
  165. for (k=0; primeTab[k] * primeTab[k] <= n ; )
  166. {
  167. DWORD prime=primeTab[k];
  168. if ( r % prime==0)
  169. {
  170. while ( r % prime==0)
  171. {
  172. add_to_facTab(prime); //增加素因子到素因子表 g_facTab
  173. r/=prime;
  174. }
  175. }
  176. k++;
  177. if ( primeTab[k] > r)
  178. break;
  179. }
  180. if (r >1)
  181. add_to_facTab(r); //增加素因子到素因子表 g_facTab
  182. }
  183. for (f_c=1,j=0;j<g_facTab.fc;j++)
  184. f_c *= (g_facTab.arr[j].e +1);
  185. //printf("%u*(%u+1)/2 with %u factor\n",i,i,f_c);
  186. if (f_c >max_fc)
  187. {
  188. printf("%u*(%u+1)/2 with %u factor\n",i,i,f_c);
  189. max_fc=f_c;
  190. }
  191. }
  192. free(primeTab);
  193. }
  194. int main(int argc, char* argv[])
  195. {
  196. double t=currTime();
  197. //check_all(92681);
  198. check_all(65535);
  199. t=currTime()-t;
  200. printf("it take %.6f ms\n",t*1000);
  201. return 0;
  202. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-11-12 22:14:59 | 显示全部楼层
版主的代码需要的时间啃下哟,学习中
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-11-29 23:07:36 | 显示全部楼层
非常感谢各位朋友的帮助,这些代码需要好好消化学习
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-11-22 04:41 , Processed in 0.021059 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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