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

[擂台] 素数分解

[复制链接]
发表于 2008-6-26 09:02:12 | 显示全部楼层
原帖由 mathe 于 2008-6-26 08:32 发表 我的想法是实际上上面代码中只有俩部分计算需要素数列表,也就是计算sumMF和sumMS部分.与其开始保存了所有素数的列表,不如俩部分都动态生成,比如保存两个长度为1,000,000左右大小范围内的素数,分别在当前iMF和iMS指向 ...
也是的。 而且你现在用的是全局变量,我一看是大数组,就没敢去调试了。 由于本题与进制无关(“回文素数”就与进制相关), 所以其效率应该是比较好的。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-6-26 09:06:29 | 显示全部楼层
原帖由 mathe 于 2008-6-26 08:58 发表 说明一下: i)开始我采用start.NextPrime(start);这种用法,不过有点不放心这种用法是否可以(毕竟输入输出在同一个地址),帮助文件里面没有说明.此外,帮助中应该还要说明函数NextPrime()会修改*this,然后返回*this; ...
在帮助文档 HugeCalc.chm::快速生成最邻近素数 Remarks 第4条中有交待:
这里的入参均声明成“CONST”,但与HugeCalc其它函数不同的是:“A.NextPrime( B )”的意义是生成比“B”更大的素数“A”,对入参的CONST限定仅表明对入参进行保护,程序内部特意没有做“A非B”的检查,以便用户可以通过反复调用“A.NextPrime( A )”而得到一个类似超大素数发生器的工具;对于函数“PreviousPrime(..)”亦类似
A.NextPrime( B ) 中,当“A非B”时,B保持为定值;否则,B(即A)才可能被修改。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-6-26 09:06:51 | 显示全部楼层
原帖由 gxqcn 于 2008-6-26 09:02 发表 也是的。 而且你现在用的是全局变量,我一看是大数组,就没敢去调试了。 由于本题与进制无关(“回文素数”就与进制相关), 所以其效率应该是比较好的。
其实只要有足够大虚拟内存就没有问题,这个大数组也就顺序访问两次
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-6-26 10:44:20 | 显示全部楼层
现在改写liangbch的一个分段筛选代码,可以开始搜索了:
  1. // HugeCalcDemo.cpp : Defines the entry point for the console application.
  2. //
  3. // Project -> Setting -> C/C++ -> Code Generation --> Use run-time library:
  4. // Win32 Debug: Debug Multithreaded DLL
  5. // Win32 Release: Multithreaded DLL
  6. // 以下代码源自 mathe 的,略有修改
  7. #include <time.h>
  8. #include <iostream>
  9. #include <stdio.h>
  10. #include <list>
  11. using namespace std;
  12. #include "../../../HugeCalc_API/CppAPI/Include/HugeCalc.h" // 公共接口
  13. #include "../../../HugeCalc_API/CppAPI/Include/HugeInt.h" // 10进制系统
  14. #include "../../../HugeCalc_API/CppAPI/Include/HugeIntX.h" // 16进制系统
  15. #pragma message( "automatic link to ../../../HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )
  16. #pragma comment( lib, "../../../HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )
  17. #define SRC_NAME "flterm.txt"
  18. #if 1
  19. #define _Test_HI
  20. #define integer CHugeInt
  21. #else
  22. #define _Test_HX
  23. #define integer CHugeIntX
  24. #endif
  25. #define MAX_N 203280220
  26. unsigned int plist[MAX_N];
  27. #include "math.h"
  28. #include "memory.h"
  29. #include "windows.h"
  30. //**********************************************
  31. // n 不能大于L2 cache,否则效能很低
  32. DWORD Sift32(DWORD n,DWORD *primeTab)
  33. // 对0到n 之间(不包括n)的数进行筛选,返回质数的个数
  34. //**********************************************
  35. {
  36. BYTE *pBuff= new BYTE[n];
  37. if (pBuff==NULL)
  38. return 0;
  39. DWORD i,sqrt_n,p;
  40. DWORD pn;
  41. //----------------------------
  42. sqrt_n=(DWORD)(sqrt((double)n)+1);
  43. while (sqrt_n * sqrt_n >=n)
  44. sqrt_n--;
  45. memset(pBuff,1,n*sizeof(BYTE));
  46. *pBuff=0;
  47. *(pBuff+1)=0; //1不是质数
  48. *(pBuff+2)=1; //2是质数
  49. for ( i=4;i<n;i+=2) //筛去2的倍数,不包括2
  50. *(pBuff+i)=0;
  51. for (i=3;i<=sqrt_n;) //i 是质数
  52. {
  53. for (p=i*i;p<n; p+=2*i)
  54. *(pBuff+p)=0; //筛去i 的奇数倍
  55. i+=2;
  56. while ( *(pBuff+i)==0 )
  57. i++; //前进到下一个质数
  58. }
  59. pn=0; //素数个数
  60. for (i=2;i<n;i++)
  61. {
  62. if (pBuff[i])
  63. {
  64. primeTab[pn++]=i;
  65. }
  66. }
  67. delete[] pBuff;
  68. return pn;
  69. }
  70. #define L2_CACHE (2*1024*1024)
  71. static DWORD getSiftBuffLength()
  72. {
  73. DWORD n=L2_CACHE * 3/4;
  74. DWORD rem=n % 30;
  75. if (rem !=0)
  76. n-=rem;
  77. return n; //n must times of 30
  78. }
  79. //**********************************************
  80. // copy prime from psrc to primeTab
  81. // mode can be 4 or 8
  82. // if mode==4, primeTab will be consider as DWORD array
  83. // if mode==8, primeTab will be conseder ad UINT64 array
  84. // return total prime Count
  85. //**********************************************
  86. int copyL1PrimeToArray(const DWORD *psrc,int srcCount,void *primeTab,int primeBuffLen, int mode)
  87. {
  88. DWORD pr;
  89. int i;
  90. pr=0;
  91. if (mode==4)
  92. {
  93. DWORD *UINT32PrimeTab=(DWORD*)primeTab;
  94. for (i=0;i<srcCount && pr<primeBuffLen;i++)
  95. {
  96. UINT32PrimeTab[pr]=psrc[i];
  97. pr++;
  98. }
  99. for (;i<srcCount;i++ )
  100. { pr++; }
  101. }
  102. else if (mode==8)
  103. {
  104. UINT64 *UINT64PrimeTab=(UINT64*)primeTab;
  105. for (i=0;i<srcCount && pr<primeBuffLen;i++)
  106. {
  107. UINT64PrimeTab[pr]=(UINT64)psrc[i];
  108. pr++;
  109. }
  110. for (;i<srcCount;i++ )
  111. { pr++; }
  112. }
  113. return pr;
  114. }
  115. //**********************************************
  116. // mode can be 4 or 8
  117. // if mode==4, primeTab will be consider as DWORD array
  118. // if mode==8, primeTab will be conseder ad UINT64 array
  119. // return total prime Count
  120. //**********************************************
  121. static UINT64 GetPrimeFromSiftBuff(const BYTE *siftBuff,UINT64 begin, UINT64 end,
  122. void *primeTab,UINT64 currCount,UINT64 primeBuffLen, int mode)
  123. {
  124. UINT64 pr;
  125. int i;
  126. pr=currCount;
  127. DWORD *UINT32PrimeTab=(DWORD*)primeTab;
  128. UINT64 *UINT64PrimeTab=(UINT64*)primeTab;
  129. //-----------------------------------
  130. if (mode==4)
  131. {
  132. for (i=0;i<end-begin && pr < primeBuffLen;i++)
  133. {
  134. if (siftBuff[i]==1)
  135. {
  136. UINT64 p=begin+(UINT64)i;
  137. UINT32PrimeTab[pr]=(DWORD)p;
  138. pr++;
  139. }
  140. }
  141. }
  142. else if (mode==8)
  143. {
  144. for (i=0;i<end-begin && pr < primeBuffLen;i++)
  145. {
  146. if (siftBuff[i]==1)
  147. {
  148. UINT64 p=begin+(UINT64)i;
  149. UINT64PrimeTab[pr]=p;
  150. pr++;
  151. }
  152. }
  153. }
  154. for (;i<end-begin;i++)
  155. {
  156. if (siftBuff[i]==1)
  157. {
  158. pr++;
  159. }
  160. }
  161. return pr;
  162. }
  163. DWORD L1PrimeBuffLen;
  164. DWORD *L1PrimeTab;
  165. DWORD L1PrimeCount;
  166. void initSift(UINT64 n)
  167. {
  168. DWORD sqrt_n;
  169. double f;
  170. sqrt_n=(DWORD)(sqrt((double)n));
  171. sqrt_n=(sqrt_n+29)/30*30;
  172. f=(double)sqrt_n*10.0/9.0+32;
  173. L1PrimeBuffLen= (DWORD)f;
  174. L1PrimeTab= new DWORD[L1PrimeBuffLen];
  175. L1PrimeCount= Sift32(sqrt_n,L1PrimeTab);
  176. }
  177. //**********************************************
  178. // 使用普通分段筛的方法筛素数,
  179. // // mode can be 4 or 8
  180. // if mode==4, primeTab will be consider as DWORD array
  181. // if mode==8, primeTab will be conseder ad UINT64 array
  182. UINT64 generalSift(UINT64 begin, UINT64 end,void *primeTab, UINT64 primeTabLimtCount)
  183. // 对0到n 之间(不包括n)的数进行筛选,返回质数的个数
  184. //**********************************************
  185. {
  186. DWORD siftBuffLen;
  187. UINT64 pr=0;
  188. siftBuffLen=end-begin;
  189. BYTE *siftBuff=new BYTE[siftBuffLen];
  190. if (siftBuff==NULL)
  191. return 0;
  192. {
  193. DWORD dwPrime,endPrime;
  194. UINT64 begIndex;
  195. DWORD endIdx;
  196. int idx,i;
  197. endIdx=end-begin;
  198. memset(siftBuff,1,siftBuffLen);
  199. endPrime= (DWORD)sqrt((double)end)+1;
  200. while (endPrime*endPrime>=end)
  201. endPrime--;
  202. i=0;
  203. while (true)
  204. {
  205. DWORD inc;
  206. UINT64 t;
  207. dwPrime=L1PrimeTab[i];
  208. if (dwPrime * dwPrime>=end)
  209. break;
  210. t=(begin+dwPrime-1)/dwPrime;
  211. if ( t<dwPrime)
  212. t=dwPrime;
  213. if (dwPrime==2)
  214. {
  215. idx=(int)(t * dwPrime-begin);
  216. while (idx<endIdx)
  217. {
  218. siftBuff[idx]=0;
  219. idx+=dwPrime;
  220. }
  221. }
  222. else
  223. {
  224. if ( t % 2==0)
  225. t++; //素数的奇数倍
  226. inc= dwPrime+dwPrime;
  227. idx=(int)(t * dwPrime-begin);
  228. while (idx<endIdx)
  229. {
  230. siftBuff[idx]=0;
  231. idx+=inc;
  232. }
  233. }
  234. i++;
  235. }
  236. pr=GetPrimeFromSiftBuff(siftBuff,begin,end,primeTab,pr,primeTabLimtCount,8);
  237. }
  238. delete[] siftBuff;
  239. return pr;
  240. }
  241. int search_match_prime(unsigned value)
  242. {
  243. int start=0,mid,end=MAX_N-1;
  244. mid=(start+end)/2;
  245. while(end-start>=2){
  246. if(plist[mid]<value){
  247. start=mid;
  248. }else{
  249. end=mid;
  250. }
  251. mid=(start+end)/2;
  252. }
  253. return mid;
  254. }
  255. bool is_list(int num, unsigned long long sum)
  256. {
  257. unsigned long long aver=sum/num;
  258. integer start(aver),end,sump(0);
  259. start.NextPrime(start);
  260. int prevc,nextc;
  261. prevc=num/2;
  262. nextc=num-1-prevc;
  263. int i;
  264. sump=end=start;
  265. for(i=0;i<nextc;i++){
  266. integer tmp(end);
  267. end.NextPrime(tmp);
  268. sump+=end;
  269. }
  270. for(i=0;i<prevc;i++){
  271. integer tmp(start);
  272. start.PreviousPrime(tmp);
  273. sump+=start;
  274. }
  275. if(sump<integer(sum)){
  276. while(sump<integer(sum)){
  277. integer newp;
  278. newp.NextPrime(end);
  279. sump+=newp-start;
  280. integer tmp(start);
  281. start.NextPrime(tmp);
  282. end=newp;
  283. }
  284. }else{
  285. while(sump>integer(sum)){
  286. integer newp;
  287. newp.PreviousPrime(start);
  288. sump-=end-newp;
  289. integer tmp(end);
  290. end.PreviousPrime(tmp);
  291. start=newp;
  292. }
  293. }
  294. return sump==integer(sum);
  295. }
  296. #define MF 2007
  297. #define MS 979
  298. void candidate(unsigned long long x)
  299. {
  300. integer y((unsigned long long)x);
  301. if(!y.IsPrime())
  302. return;
  303. if(!is_list(45,x))
  304. return;
  305. printf("Cand45: %lld\n",x);
  306. if(!is_list(17,x))
  307. return;
  308. printf("Cand17: %lld\n",x);
  309. if(!is_list(3,x))
  310. return;
  311. printf("Find: %lld\n",x);
  312. }
  313. #define BLOCK_SIZE 10000000
  314. #define TAB_LEN 689388
  315. UINT64 primeTabMF[MF+TAB_LEN];
  316. UINT64 primeTabMS[MS+TAB_LEN];
  317. UINT64 pMFblock,pMSblock;
  318. UINT64 pMFcount,pMScount;
  319. void msNextBlock()
  320. {
  321. memmove(primeTabMS,primeTabMS+pMScount-MS+1,(MS-1)*sizeof(UINT64));
  322. start:
  323. pMSblock+=BLOCK_SIZE;
  324. pMScount=generalSift(pMSblock,pMSblock+BLOCK_SIZE,primeTabMS+MS-1,TAB_LEN);
  325. if(pMScount==0)goto start;
  326. pMScount+=MS-1;
  327. }
  328. void mfNextBlock()
  329. {
  330. memmove(primeTabMF,primeTabMF+pMFcount-MF+1,(MF-1)*sizeof(UINT64));
  331. start:
  332. pMFblock+=BLOCK_SIZE;
  333. pMFcount=generalSift(pMFblock,pMFblock+BLOCK_SIZE,primeTabMF+MF-1,TAB_LEN);
  334. if(pMFcount==0)goto start;
  335. pMFcount+=MF-1;
  336. }
  337. int main(int argc, char* argv[])
  338. {
  339. int i;
  340. long long sumMF=0;
  341. long long sumMS=0;
  342. long long max_sum=2000000000000000000LL;
  343. initSift(10000000000000000LL);
  344. pMFcount=generalSift(0,BLOCK_SIZE,primeTabMF,TAB_LEN);
  345. pMScount=generalSift(0,BLOCK_SIZE,primeTabMS,TAB_LEN);
  346. printf("Init finished\n");
  347. for(i=0;i<MS;i++){
  348. sumMS+=primeTabMF[i];
  349. }
  350. sumMF=sumMS;
  351. for(;i<MF;i++){
  352. sumMF+=primeTabMF[i];
  353. }
  354. int iMF=0,iMS=0;
  355. while(sumMF<=max_sum){
  356. while(sumMS<sumMF){
  357. sumMS+=primeTabMS[iMS+MS]-primeTabMS[iMS];
  358. iMS++;
  359. if(iMS>=pMScount-MS){
  360. msNextBlock();
  361. iMS=0;
  362. }
  363. }
  364. if(sumMS==sumMF){
  365. candidate(sumMF);
  366. }
  367. sumMF+=primeTabMF[iMF+MF]-primeTabMF[iMF];
  368. iMF++;
  369. if(iMF>=pMFcount-MF){
  370. mfNextBlock();
  371. iMF=0;
  372. }
  373. }
  374. return 0;
  375. }
复制代码
不知道代码是否正确。 现在只找到两个满足本身素数以及表示成45,979,2007个素数和的结果: Cand45: 1453832430671 Cand45: 3937966662683
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-6-26 10:53:58 | 显示全部楼层
程序还有bug,运行到某一步会出错.不过这个程序调试起来太麻烦了,要运行一段时间才能够出错
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-6-26 11:14:34 | 显示全部楼层
找到一个bug, generalshft函数中: if (dwPrime * dwPrime>=end) break; 改为: if ((UINT64)dwPrime * dwPrime>=end) break;
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-6-26 11:28:15 | 显示全部楼层
谁来运行一下看看?这个程序运行完了估计能够找出一个结果来。但是估计要运行数天。我的机器明天一大早要断电一次,肯定运行不完
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-6-26 11:51:22 | 显示全部楼层
你做好了,我帮你运行
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-6-26 13:55:02 | 显示全部楼层
就上面的代码,如36楼修改了一行就可以了。但是要调用gxqcn的HugeCalc. 我的机器现在计算到和为$2*10^15$左右,还是没有一个同时是2007,979,45,17个素数和的素数。现在打印出来都是到45个素数和为止,最后几个为: Cand45: 183071317698557 Cand45: 201340432884221 Cand45: 206978108198867
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-6-26 15:03:03 | 显示全部楼层
你给我个编译后的程序,我服务器新做了 没装编译器 linux下倒可以尝试,呵呵
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-11-21 21:29 , Processed in 0.034342 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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