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

[擂台] 最小无法表达的正整数

[复制链接]
发表于 2008-8-7 09:00:17 | 显示全部楼层
任何一个瞬间的递归函数有两个状态 第一个状态是当前左子节点的所有情况 局部保存,第二个状态是所有右子节点的状态 压栈保存 ==================== 呵呵 实际代码 说简单也不简单 说复杂也不复杂 等我想好了 等我写好了 等我调试了 发上来
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-8-8 16:29:30 | 显示全部楼层
呵呵 光说原理,到现在程序还没写呢 学校有点忙 已经想明白如何做了 等写完检验吧 ================= PS: 更直接的方法也得到了 我想到 由表达式树中序遍历的序列 其特点是, 1、操作符和数字共2n-1个,操作符n-1个,数字n个 2、操作符可以任意多个并在一起, 3、如果一个从开始起的部分序列,已经有操作符k个,那么接下来,从开始算的操作数字必须也有k个,才能出现新的操作符 4、2n-1最后两个位置不得是操作符 所以如果按照上面规则,可以递归产生出合法的序列,而不用树 从而简化程序
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-8-10 21:57:53 | 显示全部楼层
补充上面的叙述 有多少连续操作符 后面就要跟多少操作数 而且最后结束的两个必须是数字 满足这两个条件的序列将为合法且为某个表达式树中序遍历序列 ========================= PS 使用栈的递归方式还是没调试好 希望两天内能调试好 否则,将直接实现本帖子的算法 (还是希望能现实现栈算法,某些题目可能有用处)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-8-10 22:01:35 | 显示全部楼层
发上当前使用栈递归的代码 但提前声明,存在错误 未调试好
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/time.h>
  4. #define max 16
  5. #define nmax 64 * 1024 * 1024
  6. int Expr[2 * max - 1]; //表达式树中序遍历序列
  7. int operator[4] = { -1, -3, -2, -4 }; // + * - /
  8. int mask[max + 1]; //代表数字是否被使用
  9. int nmask[nmax]; //表示的数字
  10. int n; //输入的n值
  11. int leaf; //剩余数字
  12. int position; //在表达式序列中的当前位置
  13. int counter; //产生的表达式计数
  14. int loop[max]; //递归栈
  15. int loopTop; //递归栈顶
  16. void
  17. init (void)
  18. {
  19. int i;
  20. for (i = 1; i <= max; i++)
  21. mask[i] = 0;
  22. position = 0;
  23. counter = 0;
  24. leaf = n;
  25. loop[loopTop++] = n - 1;
  26. //memset(nmask, 0, nmax * sizeof(int));
  27. }
  28. void
  29. search (void)
  30. {
  31. printf ("\nmin:");
  32. int i, j = 0;
  33. for (i = 1; i < nmax; i++)
  34. if (nmask[i] == 0)
  35. {
  36. j++;
  37. printf ("%d ", i);
  38. if (j == 10)
  39. break;
  40. }
  41. printf ("\n");
  42. }
  43. //返回0代表表达式合法,-1代表除法不能除尽,-2代表除以0,-3代表结果为负
  44. int
  45. printValue (void)
  46. {
  47. int i;
  48. int opTop = 0, numTop = 0;
  49. long long temp;
  50. long long numBuffer[max];
  51. int itemp;
  52. for (i = 2 * n - 2; i >= 0; i--)
  53. {
  54. if (Expr[i] < 0)
  55. {
  56. switch (Expr[i])
  57. {
  58. case -1:
  59. temp = numBuffer[numTop - 1] + numBuffer[numTop - 2];
  60. break;
  61. case -2:
  62. temp = numBuffer[numTop - 1] - numBuffer[numTop - 2];
  63. break;
  64. case -3:
  65. temp = numBuffer[numTop - 1] * numBuffer[numTop - 2];
  66. break;
  67. case -4:
  68. if (numBuffer[numTop - 2] == 0)
  69. return (-2);
  70. if (numBuffer[numTop - 1] % numBuffer[numTop - 2] > 0)
  71. return (-1);
  72. temp = numBuffer[numTop - 1] / numBuffer[numTop - 2];
  73. break;
  74. }
  75. numTop -= 1;
  76. numBuffer[numTop - 1] = temp;
  77. }
  78. else
  79. numBuffer[numTop++] = Expr[i];
  80. }
  81. temp = numBuffer[0];
  82. if (temp < 0)
  83. return (-3);
  84. if (temp < nmax)
  85. {
  86. itemp = temp;
  87. if (nmask[itemp] == 0)
  88. {
  89. counter++;
  90. printf ("%d: %d ", counter, itemp);
  91. for (i = 0; i <= 2 * n - 2; i++)
  92. {
  93. if (Expr[i] < 0)
  94. {
  95. switch (Expr[i])
  96. {
  97. case -1:
  98. printf ("+ ");
  99. break;
  100. case -2:
  101. printf ("- ");
  102. break;
  103. case -3:
  104. printf ("* ");
  105. break;
  106. case -4:
  107. printf ("/ ");
  108. break;
  109. }
  110. }
  111. else
  112. printf ("%d ", Expr[i]);
  113. }
  114. printf ("\n");
  115. nmask[itemp] = 1;
  116. }
  117. }
  118. return (0);
  119. }
  120. int
  121. print (void)
  122. {
  123. int i;
  124. for (i = 0; i <= 2 * n - 2; i++)
  125. {
  126. if (Expr[i] < 0)
  127. {
  128. switch (Expr[i])
  129. {
  130. case -1:
  131. printf ("+ ");
  132. break;
  133. case -2:
  134. printf ("- ");
  135. break;
  136. case -3:
  137. printf ("* ");
  138. break;
  139. case -4:
  140. printf ("/ ");
  141. break;
  142. }
  143. }
  144. else
  145. printf ("%d ", Expr[i]);
  146. }
  147. printf ("\n");
  148. counter++;
  149. }
  150. void
  151. printBlank (void)
  152. {
  153. counter++;
  154. }
  155. void
  156. loop1 (void)
  157. {
  158. int i, j, k;
  159. loopTop--;
  160. for (k = 0; k <= 1; k++)
  161. {
  162. Expr[position++] = operator[k];
  163. for (i = 1; i < n; i++)
  164. if (mask[i] == 0)
  165. {
  166. mask[i] = 1;
  167. Expr[position++] = i;
  168. for (j = i + 1; j <= n; j++)
  169. if (mask[j] == 0)
  170. {
  171. mask[j] = 1;
  172. Expr[position++] = j;
  173. root ();
  174. mask[j] = 0;
  175. position--;
  176. }
  177. mask[i] = 0;
  178. position--;
  179. }
  180. position--;
  181. }
  182. for (k = 2; k <= 3; k++)
  183. {
  184. Expr[position++] = operator[k];
  185. for (i = 1; i <= n; i++)
  186. if (mask[i] == 0)
  187. {
  188. mask[i] = 1;
  189. Expr[position++] = i;
  190. for (j = 1; j <= n; j++)
  191. if (mask[j] == 0)
  192. {
  193. mask[j] = 1;
  194. Expr[position++] = j;
  195. root ();
  196. mask[j] = 0;
  197. position--;
  198. }
  199. mask[i] = 0;
  200. position--;
  201. }
  202. position--;
  203. }
  204. }
  205. void
  206. loopa (int level)
  207. {
  208. int i, j, k;
  209. level--;
  210. for (k = 0; k <= 1; k++)
  211. {
  212. Expr[position++] = operator[k];
  213. for (i = 1; i <= level / 2; i++)
  214. {
  215. loop[loopTop - 1] = i;
  216. loop[loopTop++] = level - i;
  217. root ();
  218. }
  219. position--;
  220. }
  221. for (k = 2; k <= 3; k++)
  222. {
  223. Expr[position++] = operator[k];
  224. for (i = 1; i <= level - 1; i++)
  225. {
  226. loop[loopTop - 1] = i;
  227. loop[loopTop++] = level - i;
  228. root ();
  229. }
  230. position--;
  231. }
  232. }
  233. void
  234. loopl (int level)
  235. {
  236. int i, k;
  237. for (k = 0; k <= 3; k++)
  238. {
  239. Expr[position++] = operator[k];
  240. loop[loopTop - 1] = level - 1;
  241. for (i = 1; i <= n; i++)
  242. if (mask[i] == 0)
  243. {
  244. mask[i] = 1;
  245. Expr[position + 2 * level - 1] = i;
  246. root ();
  247. mask[i] = 0;
  248. }
  249. position --;
  250. }
  251. }
  252. void
  253. loopr (int level)
  254. {
  255. int i, k;
  256. for (k = 2; k <= 3; k++)
  257. {
  258. Expr[position++] = operator[k];
  259. loop[loopTop - 1] = level - 1;
  260. for (i = 1; i <= n; i++)
  261. if (mask[i] == 0)
  262. {
  263. mask[i] = 1;
  264. Expr[position++] = i;
  265. root ();
  266. mask[i] = 0;
  267. position--;
  268. }
  269. position --;
  270. }
  271. }
  272. //
  273. int
  274. root (void)
  275. {
  276. int i, j, k;
  277. int level;
  278. if (loopTop == 0)
  279. {
  280. print ();
  281. return 0;
  282. }
  283. level = loop[loopTop - 1];
  284. if (level == 1)
  285. loop1 ();
  286. else
  287. {
  288. loopl (level);
  289. loopr (level);
  290. if (level > 2)
  291. loopa (level);
  292. }
  293. }
  294. int
  295. main (void)
  296. {
  297. struct timeval start, end;
  298. double timeuse;
  299. printf ("Input n value:");
  300. scanf ("%d", &n);
  301. printf ("\n\n");
  302. gettimeofday (&start, NULL);
  303. init ();
  304. root ();
  305. printf ("\nTotal: %d\n", counter);
  306. search ();
  307. gettimeofday (&end, NULL);
  308. timeuse =
  309. 1000000 * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;
  310. timeuse /= 1000000;
  311. printf ("\n\nUsed Time:%8.6f\n\n", timeuse);
  312. return 0;
  313. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-8-16 20:08:38 | 显示全部楼层
栈似乎可以工作了 但3的对 4的不对 存在重复的数字
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/time.h>
  4. #define max 16
  5. #define nmax 64 * 1024 * 1024
  6. int Expr[2 * max - 1]; //表达式树中序遍历序列
  7. int operator[4] = { -1, -3, -2, -4 }; // + * - /
  8. int mask[max + 1]; //代表数字是否被使用
  9. int nmask[nmax]; //表示的数字
  10. int n; //输入的n值
  11. int leaf; //剩余数字
  12. int position; //在表达式序列中的当前位置
  13. int counter; //产生的表达式计数
  14. int loop[max]; //递归栈
  15. int loopTop; //递归栈顶
  16. void
  17. init (void)
  18. {
  19. int i;
  20. for (i = 1; i <= max; i++)
  21. mask[i] = 0;
  22. position = 0;
  23. counter = 0;
  24. leaf = n;
  25. loop[loopTop++] = n - 1;
  26. //memset(nmask, 0, nmax * sizeof(int));
  27. }
  28. void
  29. search (void)
  30. {
  31. printf ("\nmin:");
  32. int i, j = 0;
  33. for (i = 1; i < nmax; i++)
  34. if (nmask[i] == 0)
  35. {
  36. j++;
  37. printf ("%d ", i);
  38. if (j == 10)
  39. break;
  40. }
  41. printf ("\n");
  42. }
  43. //返回0代表表达式合法,-1代表除法不能除尽,-2代表除以0,-3代表结果为负
  44. int
  45. printValue (void)
  46. {
  47. int i;
  48. int opTop = 0, numTop = 0;
  49. long long temp;
  50. long long numBuffer[max];
  51. int itemp;
  52. for (i = 2 * n - 2; i >= 0; i--)
  53. {
  54. if (Expr[i] < 0)
  55. {
  56. switch (Expr[i])
  57. {
  58. case -1:
  59. temp = numBuffer[numTop - 1] + numBuffer[numTop - 2];
  60. break;
  61. case -2:
  62. temp = numBuffer[numTop - 1] - numBuffer[numTop - 2];
  63. break;
  64. case -3:
  65. temp = numBuffer[numTop - 1] * numBuffer[numTop - 2];
  66. break;
  67. case -4:
  68. if (numBuffer[numTop - 2] == 0)
  69. return (-2);
  70. if (numBuffer[numTop - 1] % numBuffer[numTop - 2] > 0)
  71. return (-1);
  72. temp = numBuffer[numTop - 1] / numBuffer[numTop - 2];
  73. break;
  74. }
  75. numTop -= 1;
  76. numBuffer[numTop - 1] = temp;
  77. }
  78. else
  79. numBuffer[numTop++] = Expr[i];
  80. }
  81. temp = numBuffer[0];
  82. if (temp < 0)
  83. return (-3);
  84. if (temp < nmax)
  85. {
  86. itemp = temp;
  87. if (nmask[itemp] == 0)
  88. {
  89. counter++;
  90. printf ("%d: %d ", counter, itemp);
  91. for (i = 0; i <= 2 * n - 2; i++)
  92. {
  93. if (Expr[i] < 0)
  94. {
  95. switch (Expr[i])
  96. {
  97. case -1:
  98. printf ("+ ");
  99. break;
  100. case -2:
  101. printf ("- ");
  102. break;
  103. case -3:
  104. printf ("* ");
  105. break;
  106. case -4:
  107. printf ("/ ");
  108. break;
  109. }
  110. }
  111. else
  112. printf ("%d ", Expr[i]);
  113. }
  114. printf ("\n");
  115. nmask[itemp] = 1;
  116. }
  117. }
  118. return (0);
  119. }
  120. int
  121. print (void)
  122. {
  123. int i;
  124. for (i = 0; i <= 2 * n - 2; i++)
  125. {
  126. if (Expr[i] < 0)
  127. {
  128. switch (Expr[i])
  129. {
  130. case -1:
  131. printf ("+ ");
  132. break;
  133. case -2:
  134. printf ("- ");
  135. break;
  136. case -3:
  137. printf ("* ");
  138. break;
  139. case -4:
  140. printf ("/ ");
  141. break;
  142. }
  143. }
  144. else
  145. printf ("%d ", Expr[i]);
  146. }
  147. printf ("\n");
  148. counter++;
  149. }
  150. void
  151. printBlank (void)
  152. {
  153. counter++;
  154. }
  155. void
  156. loop1 (void)
  157. {
  158. int i, j, k, t;
  159. loopTop--;
  160. for (k = 0; k <= 1; k++)
  161. {
  162. Expr[position++] = operator[k];
  163. for (i = 1; i < n; i++)
  164. if (mask[i] == 0)
  165. {
  166. mask[i] = 1;
  167. Expr[position++] = i;
  168. for (j = i + 1; j <= n; j++)
  169. if (mask[j] == 0)
  170. {
  171. mask[j] = 1;
  172. Expr[position++] = j;
  173. t = loopTop;
  174. root ();
  175. loopTop = t;
  176. mask[j] = 0;
  177. position--;
  178. }
  179. mask[i] = 0;
  180. position--;
  181. }
  182. position--;
  183. }
  184. for (k = 2; k <= 3; k++)
  185. {
  186. Expr[position++] = operator[k];
  187. for (i = 1; i <= n; i++)
  188. if (mask[i] == 0)
  189. {
  190. mask[i] = 1;
  191. Expr[position++] = i;
  192. for (j = 1; j <= n; j++)
  193. if (mask[j] == 0)
  194. {
  195. mask[j] = 1;
  196. Expr[position++] = j;
  197. t = loopTop;
  198. root ();
  199. loopTop = t;
  200. mask[j] = 0;
  201. position--;
  202. }
  203. mask[i] = 0;
  204. position--;
  205. }
  206. position--;
  207. }
  208. }
  209. void
  210. loopa (int level)
  211. {
  212. int i, j, k, t;
  213. level--;
  214. for (k = 0; k <= 1; k++)
  215. {
  216. Expr[position++] = operator[k];
  217. for (i = 1; i <= level / 2; i++)
  218. {
  219. loop[loopTop - 1] = i;
  220. t = loopTop;
  221. loop[loopTop++] = level - i;
  222. root ();
  223. loopTop = t;
  224. }
  225. position--;
  226. }
  227. for (k = 2; k <= 3; k++)
  228. {
  229. Expr[position++] = operator[k];
  230. for (i = 1; i <= level - 1; i++)
  231. {
  232. loop[loopTop - 1] = i;
  233. t = loopTop;
  234. loop[loopTop++] = level - i;
  235. root ();
  236. loopTop = t;
  237. }
  238. position--;
  239. }
  240. }
  241. void
  242. loopl (int level)
  243. {
  244. int i, k, t;
  245. for (k = 0; k <= 3; k++)
  246. {
  247. Expr[position++] = operator[k];
  248. loop[loopTop - 1] = level - 1;
  249. for (i = 1; i <= n; i++)
  250. if (mask[i] == 0)
  251. {
  252. mask[i] = 1;
  253. Expr[position + 2 * level - 1] = i;
  254. t = loopTop; //new
  255. root ();
  256. loopTop = t; //new
  257. mask[i] = 0;
  258. }
  259. position --;
  260. }
  261. }
  262. void
  263. loopr (int level)
  264. {
  265. int i, k, t;
  266. for (k = 2; k <= 3; k++)
  267. {
  268. Expr[position++] = operator[k];
  269. loop[loopTop - 1] = level - 1;
  270. for (i = 1; i <= n; i++)
  271. if (mask[i] == 0)
  272. {
  273. mask[i] = 1;
  274. Expr[position++] = i;
  275. t = loopTop; //new
  276. root ();
  277. loopTop = t; //new
  278. mask[i] = 0;
  279. position--;
  280. }
  281. position --;
  282. }
  283. }
  284. //
  285. int
  286. root (void)
  287. {
  288. int i, j, k;
  289. int level;
  290. if (loopTop == 0)
  291. {
  292. print ();
  293. return 0;
  294. }
  295. level = loop[loopTop - 1];
  296. if (level == 1)
  297. loop1 ();
  298. else
  299. {
  300. loopl (level);
  301. loopr (level);
  302. if (level > 2)
  303. loopa (level);
  304. }
  305. }
  306. int
  307. main (void)
  308. {
  309. struct timeval start, end;
  310. double timeuse;
  311. printf ("Input n value:");
  312. scanf ("%d", &n);
  313. printf ("\n\n");
  314. gettimeofday (&start, NULL);
  315. init ();
  316. root ();
  317. printf ("\nTotal: %d\n", counter);
  318. search ();
  319. gettimeofday (&end, NULL);
  320. timeuse =
  321. 1000000 * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;
  322. timeuse /= 1000000;
  323. printf ("\n\nUsed Time:%8.6f\n\n", timeuse);
  324. return 0;
  325. }
复制代码
[ 本帖最后由 无心人 于 2008-8-16 20:38 编辑 ]
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-8-16 21:58:28 | 显示全部楼层
mathe: 有现成程序快速的对具体的数字m求连续n个数字的四则表示么?? 我想,我不完整程序版本33#的速度似乎快很多 可修改之使输出连续32个无法表示的 我们可从最小的一个个排除 修改下面的函数
  1. #define SearchMax 32
  2. void
  3. search (void)
  4. {
  5. printf ("\nmin:");
  6. int i, j = 0;
  7. for (i = 1; i < nmax; i++)
  8. if (nmask[i] == 0)
  9. {
  10. j++;
  11. printf ("%d ", i);
  12. if (j == SearchMax)
  13. break;
  14. }
  15. printf ("\n");
  16. }
复制代码
刚对11的测试,输出到48733项 48730: 20994 + 1 + 2 + 3 + 8 + 10 * 5 * 9 + 4 * 6 * 7 11 48731: 20634 + 1 + 2 + 3 + 8 + 10 * 5 * 9 - * 6 * 7 11 4 48732: 13614 + 1 + 2 + 3 + 8 + 10 * 5 * 9 - * 4 * 7 11 6 48733: 16686 + 1 + 2 + 3 + 8 + 10 * 6 + 5 * 4 * 7 * 9 11 real 4m57.256s user 3m35.929s sys 0m2.212s 估计11的要输出500万项以上吧 最小无法表示的当在200万-400万之间 这么作唯一的担心是输出32个连续最小无法表示的是否足够 或者干脆是把无法表示的输出个10000个到文件? [ 本帖最后由 无心人 于 2008-8-16 22:18 编辑 ]
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-8-18 12:28:46 | 显示全部楼层
也许可以快速构造部分表达式。 不过这种方法最大的问题在于后面构造失败以后,如何去证明后面那个数不存在合法的表达式(而且如果实际上合法表达式存在,那么更加麻烦)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-8-18 12:53:15 | 显示全部楼层
我有点不明白你的意思 你是否说这个意思 假设对于小于等于 $f(n)=3 / 2 n!$(1-n构造的四则运算结果所有可能数字中最大的)的正整数 用不完全构造的方法没构造出表达式的 数字组成集合 $Fa$ 对集合中的数字 有没有确定方法证明存在构造表达式? [ 本帖最后由 无心人 于 2008-8-18 12:56 编辑 ]
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-8-18 12:59:20 | 显示全部楼层
我想这个问题可以提出 另外一个问题 对于确定的正整数$N$ 是否存在$1..n$的$n$个数字 构造的四则运算式 使得结果是$N$ 我觉得这个问题比本帖子讨论的问题简单的多
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-8-18 13:04:24 | 显示全部楼层
以n = 11为例 可证明最大可构造表达式值是59875200 最小不可构造数字大于n=10的不可构造数字 假设不完全构造后 得到无法构造的数字序列 其最小值应该大于n=10的确定的最小值a 即使小于 也应该能证明小于11a且大于a的数字应该绝大部分能构造 呵呵,所以我想问你是否存在程序能构造具体数字的表达式
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-11-21 20:34 , Processed in 0.033943 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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