084.素数幻方

举报
C语言与CPP编程 发表于 2022/05/02 00:46:43 2022/05/02
【摘要】 #include<stdio.h>#include<math.h>int number[210][5]; /*存放可逆素数及素数分解后的各位数字*/int select[110]; /*可以放在矩阵第一行和最后一行的素数的下标*/ int array[4][5]; /...

  
  1. #include<stdio.h>
  2. #include<math.h>
  3. int number[210][5]; /*存放可逆素数及素数分解后的各位数字*/
  4. int select[110]; /*可以放在矩阵第一行和最后一行的素数的下标*/
  5. int array[4][5]; /*4X4的矩阵,每行0号元素存可逆素数对应的数组下标*/
  6. int count; /*可逆素数的数目*/
  7. int selecount; /*可以放在矩阵第一行和最后一行的可逆素数的数目*/
  8. int larray[2][200]; /*存放素数前二、三位数的临时数组所对应的数量计数器*/
  9. int lcount[2];
  10. int num(int number);
  11. int ok(int number);
  12. void process(int i);
  13. void copy_num(int i);
  14. int comp_num(int n);
  15. int find1(int i);
  16. int find2(void);
  17. int find0(int num);
  18. void p_array(void);
  19. FILE *fp;
  20. void main()
  21. {
  22. int i,k,flag,cc=0,i1,i4;
  23. clrscr();
  24. if((fp=fopen("Exa70data.dat","w+"))==NULL)
  25. {
  26. printf("\n Can't create file Exa70data.dat !\n");
  27. exit(0);
  28. }
  29. printf("there are magic squares with invertable primes as follw:\n");
  30. for(i=1001;i<9999;i+=2) /*求满足条件的可逆素数*/
  31. {
  32. k=i/1000;
  33. if(k%2!=0&&k!=5&&num(i)) /*若可逆素数的第一位不是偶数或5*/
  34. {
  35. number[count][0]=i; /*存入数组*/
  36. process(count++); /*分解素数的各位数字*/
  37. if(number[count-1][2]%2!=0&& /*若可逆素数满足放在矩阵第一行*/
  38. number[count-1][3]%2!=0&& /*和最后一行的条件,记录可逆素数的*/
  39. number[count-1][2]!=5&& /*下标,计数器加1*/
  40. number[count-1][3]!=5)
  41. select[selecount++]=count-1;
  42. }
  43. }
  44. larray[0][lcount[0]++]=number[0][0]/100; /*临时数组的第一行存前二位*/
  45. larray[1][lcount[1]++]=number[0][0]/10; /*临时数组的第二行存前三位*/
  46. for(i=1;i<count;i++) /*将素数不重复的前二、三位存入临时数组中*/
  47. {
  48. if(larray[0][lcount[0]-1]!=number[i][0]/100)
  49. larray[0][lcount[0]++]=number[i][0]/100;
  50. if(larray[1][lcount[1]-1]!=number[i][0]/10)
  51. larray[1][lcount[1]++]=number[i][0]/10;
  52. }
  53. for(i1=0;i1<selecount;i1++) /*在第一行允许的汇聚围内穷举*/
  54. {
  55. array[0][0]=select[i1]; /*取对应的素数下标*/
  56. copy_num(0); /*复制分解的素数*/
  57. for(array[1][0]=0;array[1][0]<count;array[1][0]++) /*穷举第二行*/
  58. {
  59. copy_num(1); /*复制分解的数字*/
  60. if(!comp_num(2))
  61. continue; /*若每列的前两位的组成与素数相矛盾,则试探下一个数*/
  62. for(array[2][0]=0;array[2][0]<count;array[2][0]++) /*穷举第三行*/
  63. {
  64. copy_num(2); /*复制分解的数字*/
  65. if(!comp_num(3))
  66. continue; /*若每列的前三位的组成与素数相矛盾,则试探下一个数*/
  67. for(i4=0;i4<selecount;i4++) /*在最后一行允许的范围内穷举*/
  68. {
  69. array[3][0]=select[i4];
  70. copy_num(3); /*复制分解的数字*/
  71. for(flag=1,i=1;flag&&i<=4;i++) /*判断每列是否可逆素数*/
  72. if(!find1(i))flag=0;
  73. if(flag&&find2()) /*判断对角线是否为可逆素数*/
  74. { printf("No.%d\n",++cc);
  75. fprintf(fp,"No.%d\n",cc);
  76. p_array();
  77. } /*输出幻方矩阵*/
  78. }
  79. }
  80. }
  81. }
  82. fclose(fp);
  83. puts("\n Press any key to quit...");
  84. getch();
  85. }
  86. int num(int number) /*判断是否可逆素数*/
  87. {
  88. int j;
  89. if(!ok(number)) return 0;
  90. for(j=0;number>0;number/=10) /*将素数变为反序数*/
  91. j=j*10+number%10;
  92. if(!ok(j)) return 0; /*判断反序数是否为素数*/
  93. return 1;
  94. }
  95. int ok(int number) /*判断是否为素数*/
  96. {
  97. int i,j;
  98. if(number%2==0) return 0;
  99. j=sqrt((double)number)+1;
  100. for(i=3;i<=j;i+=2)
  101. if(number%i==0) return 0;
  102. return 1;
  103. }
  104. void process(int i) /*将第i个整数分解为数字并存入数组*/
  105. {
  106. int j,num;
  107. num=number[i][0];
  108. for(j=4;j>=1;j--,num/=10)
  109. number[i][j]=num%10;
  110. }
  111. void copy_num(int i) /*将array[i][0]指向的素数的各位数字复制到array[i]中*/
  112. {
  113. int j;
  114. for(j=1;j<=4;j++)
  115. array[i][j]=number[array[i][0]][j];
  116. }
  117. int comp_num(int n) /*判断array中每列的前n位是否与可逆素数允许的前n位矛盾*/
  118. {
  119. static int ii; /*用内部静态变量保存前一次查找到的元素下标*/
  120. static int jj; /*ii:前一次查找前二位的下标,jj:前一次查找前三位的下标*/
  121. int i,num,k,*p; /*p:指向对应的要使用的前一次下标ii或jj*/
  122. int *pcount; /*pcount:指向要使用的临时数组数量的计数器*/
  123. switch(n){ /*根据n的值选择对应的一组控制变量*/
  124. case 2:pcount=&lcount[0];p=&ii;break;
  125. case 3:pcount=&lcount[1];p=&jj;break;
  126. default:return 0;
  127. }
  128. for(i=1;i<=4;i++) /*对四列分别进行处理*/
  129. {
  130. for(num=0,k=0;k<n;k++) /*计算前n位数字代表的数值*/
  131. num=num*10+array[k][i];
  132. if(num<=larray[n-2][*p]) /*与前一次最后查找到的元素进行比较*/
  133. for(;*p>=0&&num<larray[n-2][*p];(*p)--);/*若前次查找到的元素大,则向前找*/
  134. else
  135. for(;p<pcount&&num>larray[n-2][*p];(*p)++); /*否则向后找*/
  136. if(*p<0||*p>=*pcount)
  137. {
  138. *p=0; return 0;
  139. }
  140. if(num!=larray[n-2][*p])
  141. return 0; /*前n位不是可逆素数允许的值则返回0*/
  142. }
  143. return 1;
  144. }
  145. int find1(int i) /*判断列方向是否是可逆素数*/
  146. {
  147. int num,j;
  148. for(num=0,j=0;j<4;j++)
  149. num=num*10+array[j][i];
  150. return find0(num);
  151. }
  152. int find2(void) /*判断对角线方向是否是可逆素数*/
  153. {
  154. int num1,num2,i,j;
  155. for(num1=0,j=0;j<4;j++)
  156. num1=num1*10+array[j][j+1];
  157. for(num2=0,j=0,i=4;j<4;j++,i--)
  158. num2=num2*10+array[j][i];
  159. if(find0(num1)) return(find0(num2));
  160. else return 0;
  161. }
  162. int find0(int num) /*查找是否为满足要求的可逆素数*/
  163. {
  164. static int j;
  165. if(num<=number[j][0])for(;j>=0&&num<number[j][0];j--);
  166. else for(;j<count&&num>number[j][0];j++);
  167. if(j<0||j>=count){ j=0;return 0; }
  168. if(num==number[j][0]) return 1;
  169. else return 0;
  170. }
  171. void p_array(void) /*输出矩阵*/
  172. {
  173. int i,j;
  174. for(i=0;i<4;i++)
  175. {
  176. for(j=1;j<=4;j++)
  177. {
  178. printf("%d ",array[i][j]);
  179. fprintf(fp,"%d ",array[i][j]);
  180. }
  181. printf("\n");
  182. fprintf(fp,"\n");
  183. }
  184. }

文章来源: blog.csdn.net,作者:程序员编程指南,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_41055260/article/details/124518679

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。