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

[求助] 关于一个运算优化的问题

[复制链接]
 楼主| 发表于 2009-3-20 04:05:19 | 显示全部楼层
我也贴个C#,看看对大家的思路有没有帮助,这道题的平均水平都被大家带高了! 呵呵!
  1. class Program1318Xor
  2. {
  3. class BigIntCompare : IComparer<BigInt>
  4. {
  5. public int Compare(BigInt x, BigInt y)
  6. {
  7. for (int i = 3; i >= 0; i--)
  8. {
  9. if (x.Items[i] > y.Items[i])
  10. return 1;
  11. else if ((x.Items[i] < y.Items[i]))
  12. return -1;
  13. }
  14. return 0;
  15. }
  16. }
  17. class BigInt
  18. {
  19. public uint[] Items;
  20. public BigInt(string str)
  21. {
  22. string[] item = str.Split(' ');
  23. Items = new uint[4];
  24. for (int i = 0; i < 4; i++)
  25. Items[3 - i] = uint.Parse(item[i]);
  26. }
  27. public BigInt()
  28. {
  29. Items = new uint[4];
  30. }
  31. public BigInt(uint A)
  32. {
  33. Items = new uint[4];
  34. Items[0] = A;
  35. }
  36. public bool BitNum(int index)
  37. {
  38. int bit = index >> 5;
  39. int current = index - (bit << 5);
  40. return ((Items[bit] >> current) & 1) == 1;
  41. }
  42. public int FirstIndexOfOne()
  43. {
  44. for (int i = 3; i >= 0; i--)
  45. {
  46. if (Items[i] == 0)
  47. continue;
  48. for (int j = 31; j >= 0; j--)
  49. {
  50. if (((Items[i] >> j) & 1) == 1)
  51. return (j + (i << 5));
  52. }
  53. }
  54. return 0;
  55. }
  56. public int IndexOfOne(int start)
  57. {
  58. while (start > 0 && !BitNum(start))
  59. start--;
  60. return start;
  61. }
  62. public static BigInt operator *(BigInt A, uint B)
  63. {
  64. BigInt result = new BigInt();
  65. ulong mTemp = 0;
  66. uint cTemp = 0;
  67. for (int i = 0; i < 4; i++)
  68. {
  69. mTemp = (ulong)A.Items[i] * (ulong)B;
  70. result.Items[i] = (uint)(mTemp & 0xFFFFFFFF);
  71. result.Items[i] += cTemp;
  72. cTemp = (uint)(mTemp >> 32);
  73. }
  74. if (cTemp != 0)
  75. return null;
  76. return result;
  77. }
  78. }
  79. private static List<BigInt> AllNumber;
  80. private static List<int> AllCount;
  81. private static List<int> AllAccumlation;
  82. private static List<BigInt> PowerOf10;
  83. private static int[] PowerOf10Log;
  84. static void solve()
  85. {
  86. preOperation();
  87. AllNumber = new List<BigInt>();
  88. AllCount = new List<int>();
  89. AllAccumlation = new List<int>();
  90. int N = int.Parse(Console.ReadLine());
  91. //int N = 100;
  92. BigInt bInt;
  93. for (int i = 0; i < N; i++)
  94. {
  95. bInt = new BigInt(Console.ReadLine());
  96. //bInt = new BigInt((uint)i);
  97. AllNumber.Add(bInt);
  98. }
  99. AllNumber.Sort(new BigIntCompare().Compare);
  100. int hbit = AllNumber[AllNumber.Count - 1].FirstIndexOfOne();
  101. int position = 0;
  102. AllCount.Add(1);
  103. AllAccumlation.Add(0);
  104. for (int i = 1; i < AllNumber.Count; i++)
  105. {
  106. if (Compare(AllNumber[i], AllNumber[position], hbit) != 0)
  107. {
  108. position++;
  109. AllNumber[position] = AllNumber[i];
  110. AllAccumlation.Add(i);
  111. AllCount.Add(1);
  112. }
  113. else
  114. AllCount[position]++;
  115. }
  116. AllAccumlation.Add(AllNumber.Count);
  117. AllNumber.RemoveRange(position + 1, AllNumber.Count - position - 1);
  118. ulong sum = calculateSame(AllNumber.Count - 1, 0, hbit);
  119. Console.WriteLine(sum << 1);
  120. }
  121. //计算相同的段
  122. static ulong calculateSame(int start, int end, int depth)
  123. {
  124. if (start == end || PowerOf10Log[depth] == 0)
  125. return 0;
  126. int hBit = AllNumber[start].IndexOfOne(depth);
  127. int power = PowerOf10Log[hBit];
  128. if (power == 0)
  129. return 0;
  130. if (start == end + 1)
  131. return (ulong)(LogXor(AllNumber[start], AllNumber[end], hBit) * AllCount[start] * AllCount[end]);
  132. int mid = -1;
  133. for (int i = start; i >= end; i--)
  134. {
  135. if (!AllNumber[i].BitNum(hBit))
  136. {
  137. mid = i;
  138. break;
  139. }
  140. }
  141. if (mid == -1)
  142. return calculateSame(start, end, hBit - 1);
  143. ulong sumUpper = calculateSame(start, mid + 1, hBit - 1);
  144. ulong sumLower = calculateSame(mid, end, hBit - 1);
  145. ulong sum = sumUpper + sumLower;
  146. if (power < 0)
  147. sum += (ulong)((AllAccumlation[start + 1] - AllAccumlation[mid + 1]) * (AllAccumlation[mid + 1] - AllAccumlation[end]) * power * -1);
  148. else
  149. sum += calculateDiff(start, mid + 1, mid, end, hBit, hBit - 1);
  150. return sum;
  151. }
  152. //计算不同的两个段
  153. static ulong calculateDiff(int startUpper, int endUpper, int startLower, int endLower, int hBit, int depth)
  154. {
  155. if (startUpper < endUpper || startLower < endLower)
  156. return 0;
  157. if (startUpper == endUpper && startLower == endLower)
  158. return (ulong)(LogXor(AllNumber[startUpper], AllNumber[startLower], hBit) * AllCount[startUpper] * AllCount[startLower]);
  159. int power = PowerOf10Log[hBit];
  160. ulong sum = 0;
  161. int midUpper = endUpper - 1;
  162. int midLower = endLower - 1;
  163. bool bit10 = PowerOf10[power].BitNum(depth);
  164. for (int i = startUpper; i >= endUpper; i--)
  165. {
  166. if (!AllNumber[i].BitNum(depth))
  167. {
  168. midUpper = i;
  169. break;
  170. }
  171. }
  172. for (int i = startLower; i >= endLower; i--)
  173. {
  174. if (!AllNumber[i].BitNum(depth))
  175. {
  176. midLower = i;
  177. break;
  178. }
  179. }
  180. if (bit10)
  181. {
  182. //Xor为0的都=power-1
  183. sum += (ulong)((AllAccumlation[startUpper + 1] - AllAccumlation[midUpper + 1]) * (AllAccumlation[startLower + 1] - AllAccumlation[midLower + 1]) * (power - 1));
  184. sum += (ulong)((AllAccumlation[midUpper + 1] - AllAccumlation[endUpper]) * (AllAccumlation[midLower + 1] - AllAccumlation[endLower]) * (power - 1));
  185. sum += calculateDiff(startUpper, midUpper + 1, midLower, endLower, hBit, depth - 1);
  186. sum += calculateDiff(midUpper, endUpper, startLower, midLower + 1, hBit, depth - 1);
  187. }
  188. else
  189. {
  190. //Xor为1的都=power
  191. sum += (ulong)((AllAccumlation[startUpper + 1] - AllAccumlation[midUpper + 1]) * (AllAccumlation[midLower + 1] - AllAccumlation[endLower]) * power);
  192. sum += (ulong)((AllAccumlation[midUpper + 1] - AllAccumlation[endUpper]) * (AllAccumlation[startLower + 1] - AllAccumlation[midLower + 1]) * power);
  193. sum += calculateDiff(startUpper, midUpper + 1, startLower, midLower + 1, hBit, depth - 1);
  194. sum += calculateDiff(midUpper, endUpper, midLower, endLower, hBit, depth - 1);
  195. }
  196. return sum;
  197. }
  198. static void preOperation()
  199. {
  200. PowerOf10 = new List<BigInt>();
  201. PowerOf10Log = new int[128];
  202. BigInt bInt = new BigInt(1);
  203. int hbit;
  204. while (bInt != null)
  205. {
  206. hbit = bInt.FirstIndexOfOne();
  207. PowerOf10Log[hbit] = PowerOf10.Count;
  208. PowerOf10.Add(bInt);
  209. bInt *= 10;
  210. }
  211. int current = 0;
  212. for (int i = 0; i < PowerOf10Log.Length; i++)
  213. {
  214. if (PowerOf10Log[i] == 0)
  215. PowerOf10Log[i] = current * -1;
  216. else
  217. current = PowerOf10Log[i];
  218. }
  219. }
  220. static int LogXor(BigInt A, BigInt B, int hbit)
  221. {
  222. int startbit = hbit >> 5;
  223. int current = startbit + 1;
  224. uint firstbit = 0;
  225. while (firstbit == 0)
  226. {
  227. current--;
  228. firstbit = A.Items[current] ^ B.Items[current];
  229. }
  230. if (startbit == current)
  231. startbit = hbit - (current << 5);
  232. else
  233. startbit = 31;
  234. for (int i = startbit; i > 0; i--)
  235. {
  236. if (((firstbit >> i) & 1) == 1)
  237. {
  238. startbit = i;
  239. break;
  240. }
  241. }
  242. hbit = (current << 5) + startbit;
  243. int power = PowerOf10Log[hbit];
  244. if (power == 0)
  245. return 0;
  246. if (power < 0)
  247. return power * -1;
  248. if (firstbit > PowerOf10[power].Items[current])
  249. return power;
  250. if (firstbit < PowerOf10[power].Items[current])
  251. return power - 1;
  252. for (int i = current - 1; i >= 0; i--)
  253. {
  254. firstbit = A.Items[i] ^ B.Items[i];
  255. if (PowerOf10[power].Items[i] > firstbit)
  256. return power - 1;
  257. else if (PowerOf10[power].Items[i] < firstbit)
  258. return power;
  259. }
  260. return power;
  261. }
  262. static int Compare(BigInt x, BigInt y, int bit)
  263. {
  264. for (int i = bit >> 5; i >= 0; i--)
  265. {
  266. if (x.Items[i] > y.Items[i])
  267. return 1;
  268. else if (x.Items[i] < y.Items[i])
  269. return -1;
  270. }
  271. return 0;
  272. }
  273. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-20 09:07:25 | 显示全部楼层

回复 151# litaoye 的帖子

( ⊙o⊙ ),都四更了,还在工作。。。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-20 09:31:59 | 显示全部楼层
楼主应该注意休息,经常熬夜对身体伤害很大。我现在尽量在12点前睡觉。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-20 10:22:33 | 显示全部楼层
宝宝也老熬夜啊?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-3-20 23:29:14 | 显示全部楼层

回复 153# liangbch 的帖子

过了这段时间可能就好了,谢谢提醒!呵呵!
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-22 14:59:59 | 显示全部楼层
原帖由 liangbch 于 2009-3-19 10:24 发表 我从0.342优化到0.171,如果优化后速度再提高一倍,就是第一名了。按照楼主的思路,将XOR和log10这2步操作合在一起,用汇编语言写成一个函数,速度应该可以更快。等有时间我将尝试一下。
我现在最好成绩0.078,打破了shshsh_0510的0.093的记录。 1. 先完全汇编语言编写xorLog10,速度提高到0.14秒 2. 然后在计算之前,将至多5000个UINT128 进行了排序,速度不降反增,速度竟提高到0.109. 3.将xorLog10进行调整,减少了指令条数。测试结果为0.093或者0.078

评分

参与人数 2威望 +2 鲜花 +2 收起 理由
litaoye + 1 + 1
shshsh_0510 + 1 + 1 0.078

查看全部评分

毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-3-23 01:07:27 | 显示全部楼层

回复 156# liangbch 的帖子

呵呵,这个成绩c#是无论如何也不可能打破的了!确实很棒! 最近发现这个时间误差有时还是挺大的!
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-23 08:33:59 | 显示全部楼层
宝宝的代码我看看 logxor如果用xmm最合适了 log10我的还存在一个跳转无法消 不知你的如何? [hide=1000000000000000000000000000000000] 给我elflyao@foxmail.com [/hide]
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-23 08:42:32 | 显示全部楼层
我想C++如果深度汇编优化,打入前三问题不大
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-3-23 09:03:14 | 显示全部楼层
  1. typedef struct
  2. {
  3. unsigned int d[4];
  4. } UINT128;
  5. unsigned int CompTable[128][2] = {0,0, 0,0, 0,0, 0,1, 1,0, 1,0, 1,1, 2,0, 2,0, 2,1, 3,0, 3,0, 3,0, 3,1,
  6. 4,0,4,0,4,1,5,0,5,0,5,1,6,0,6,0,6,0,6,1,7,0,7,0,7,1,8,0,8,0,
  7. 8,1,9,0,9,0,9,0,9,1,10,0,10,0,10,1,11,0,11,0,11,1,12,0,12,
  8. 0,12,0,12,1,13,0,13,0,13,1,14,0,14,0,14,1,15,0,15,0,15,0,15,
  9. 1,16,0,16,0,16,1,17,0,17,0,17,1,18,0,18,0,18,0,18,1,19,0,19,
  10. 0,19,1,20,0,20,0,20,1,21,0,21,0,21,0,21,1,22,0,22,0,22,1,23,
  11. 0,23,0,23,1,24,0,24,0,24,0,24,1,25,0,25,0,25,1,26,0,26,0,26,
  12. 1,27,0,27,0,27,0,27,1,28,0,28,0,28,1,29,0,29,0,29,1,30,0,30,
  13. 0,30,1,31,0,31,0,31,0,31,1,32,0,32,0,32,1,33,0,33,0,33,1,34,
  14. 0,34,0,34,0,34,1,35,0,35,0,35,1,36,0,36,0,36,1,37,0,37,0,37,0,37,1,38,0};
  15. UINT128 pow10[40] = {1,0,0,0,
  16. 10,0,0,0,
  17. 100,0,0,0,
  18. 1000,0,0,0,
  19. 10000,0,0,0,
  20. 100000,0,0,0,
  21. 1000000,0,0,0,
  22. 10000000,0,0,0,
  23. 100000000,0,0,0,
  24. 1000000000,0,0,0,
  25. 1410065408,2,0,0,
  26. 1215752192,23,0,0,
  27. 3567587328,232,0,0,
  28. 1316134912,2328,0,0,
  29. 276447232,23283,0,0,
  30. 2764472320,232830,0,0,
  31. 1874919424,2328306,0,0,
  32. 1569325056,23283064,0,0,
  33. 2808348672,232830643,0,0,
  34. 2313682944,2328306436,0,0,
  35. 1661992960,1808227885,5,0,
  36. 3735027712,902409669,54,0,
  37. 2990538752,434162106,542,0,
  38. 4135583744,46653770,5421,0,
  39. 2701131776,466537709,54210,0,
  40. 1241513984,370409800,542101,0,
  41. 3825205248,3704098002,5421010,0,
  42. 3892314112,2681241660,54210108,0,
  43. 268435456,1042612833,542101086,0,
  44. 2684354560,1836193738,1126043566,1,
  45. 1073741824,1182068202,2670501072,12,
  46. 2147483648,3230747430,935206946,126,
  47. 0,2242703233,762134875,1262,
  48. 0,952195850,3326381459,12621,
  49. 0,932023908,3199043520,126217,
  50. 0,730304488,1925664130,1262177,
  51. 0,3008077584,2076772117,12621774,
  52. 0,16004768,3587851993,126217744,
  53. 0,160047680,1518781562,1262177448,
  54. 0, 0, 0, 0};
  55. __declspec(naked)
  56. int __fastcall log_10(UINT128 * n)
  57. {
  58. __asm
  59. {
  60. bsr edx, [ecx]
  61. bsr eax, [ecx + 4]
  62. add eax, 32
  63. cmp [ecx + 4], 0
  64. cmovne edx, eax
  65. bsr eax, [ecx + 8]
  66. add eax, 64
  67. cmp [ecx + 8], 0
  68. cmovne edx, eax
  69. bsr eax, [ecx + 12]
  70. add eax, 96
  71. cmp [ecx + 12], 0
  72. cmovne edx, eax
  73. mov eax, dword ptr CompTable[8 * edx]
  74. cmp dword ptr CompTable[8 * edx + 4], 0
  75. je ex
  76. add eax, 1
  77. mov edx, eax
  78. shl edx, 4
  79. push ebx
  80. mov ebx, [ecx]
  81. sub ebx, pow10[edx]
  82. mov ebx, [ecx + 4]
  83. sbb ebx, pow10[edx + 4]
  84. mov ebx, [ecx + 8]
  85. sbb ebx, pow10[edx + 8]
  86. mov ebx, [ecx + 12]
  87. sbb ebx, pow10[edx + 12]
  88. sbb ebx, ebx
  89. add eax, ebx
  90. pop ebx
  91. ex:
  92. ret
  93. }
  94. }
复制代码
log10的汇编版本
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-11-18 15:42 , Processed in 0.039308 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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