Максимум без условных конструкций (Нибо Амир)

  1. Program nuinu;
  2.  
  3. var a,b,otv,a1,b1:ShortInt;
  4. c,d,ans,c1,cz,d1,dz,mak1,mak2,k,mask,post,sluch,v1,v2,w,x1,x2,sum,copmask:Byte;
  5. begin
  6. readln(a,b);
  7. c:=Byte(a);
  8. d:=Byte(b);
  9. k:= 1-((c shr 7) xor (d shr 7));
  10. k:=k shl 7;
  11. c:=c or k;
  12. d:=d or k;
  13. c1:=c xor 128;
  14. cz:=c1 shr 7;
  15. mak1:=cz;
  16. mak1:=(mak1 shl 1)+cz;
  17. mak1:=(mak1 shl 1)+cz;
  18. mak1:=(mak1 shl 1)+cz;
  19. mak1:=(mak1 shl 1)+cz;
  20. mak1:=(mak1 shl 1)+cz;
  21. mak1:=(mak1 shl 1)+cz;
  22. mak1:=(mak1 shl 1)+cz;
  23. mak1:=(mak1 shl 1)+cz;
  24. c1:=c1 and mak1;
  25. d1:=d xor 128;
  26. dz:=d1 shr 7;
  27. mak2:=dz;
  28. mak1:=(mak2 shl 1)+dz;
  29. mak2:=(mak2 shl 1)+dz;
  30. mak2:=(mak2 shl 1)+dz;
  31. mak2:=(mak2 shl 1)+dz;
  32. mak2:=(mak2 shl 1)+dz;
  33. mak2:=(mak2 shl 1)+dz;
  34. mak2:=(mak2 shl 1)+dz;
  35. mak2:=(mak2 shl 1)+dz;
  36. d1:=d1 and mak2;
  37. ans:=(c1+d1) shl 1;
  38. ans:=ans shr 1;
  39. c:=Byte(a);
  40. d:=Byte(b);
  41. k:= (c shr 7) and (d shr 7);
  42. sluch:=(1-(c shr 7)) and (1-(d shr 7)) or (c shr 7) and (d shr 7);
  43. post:=k or sluch;
  44. c:=((a xor 255) +1)*k+(1-k)*a;
  45. d:=((b xor 255) +1)*k+(1-k)*b;
  46. mask:=c xor d;
  47. copmask:=mask;
  48. sum:=(copmask shr 7);
  49. copmask:=copmask shl 1;
  50. sum:=sum or (copmask shr 7);
  51. copmask:=copmask shl 1;
  52. sum:=sum or (copmask shr 7);
  53. copmask:=copmask shl 1;
  54. sum:=sum or (copmask shr 7);
  55. copmask:=copmask shl 1;
  56. sum:=sum or (copmask shr 7);
  57. copmask:=copmask shl 1;
  58. sum:=sum or (copmask shr 7);
  59. copmask:=copmask shl 1;
  60. sum:=sum or (copmask shr 7);
  61. copmask:=copmask shl 1;
  62. sum:=sum or (copmask shr 7);
  63. v1:=(c and mask)*sum+(1-sum)*c;
  64. v2:=d and mask;
  65. x1:=v1 shr 7;
  66. x2:=v2 shr 7;
  67. c:=c*((1-x2) or x1);
  68. d:=d*((1-x1) or x2);
  69. w:=((1-x2) or x1) xor ((1-x1) or x2);
  70. v1:=v1 shl 1;
  71. v2:=v2 shl 1;
  72. x1:=v1 shr 7;
  73. x2:=v2 shr 7;
  74. c:=c*(w or ((1-x2) or x1));
  75. d:=d*(w or ((1-x1) or x2));
  76. w:=w or (((1-x2) or x1) xor ((1-x1) or x2));
  77. v1:=v1 shl 1;
  78. v2:=v2 shl 1;
  79. x1:=v1 shr 7;
  80. x2:=v2 shr 7;
  81. c:=c*(w or ((1-x2) or x1));
  82. d:=d*(w or ((1-x1) or x2));
  83. w:=w or (((1-x2) or x1) xor ((1-x1) or x2));
  84. v1:=v1 shl 1;
  85. v2:=v2 shl 1;
  86. x1:=v1 shr 7;
  87. x2:=v2 shr 7;
  88. c:=c*(w or ((1-x2) or x1));
  89. d:=d*(w or ((1-x1) or x2));
  90. w:=w or (((1-x2) or x1) xor ((1-x1) or x2));
  91. v1:=v1 shl 1;
  92. v2:=v2 shl 1;
  93. x1:=v1 shr 7;
  94. x2:=v2 shr 7;
  95. c:=c*(w or ((1-x2) or x1));
  96. d:=d*(w or ((1-x1) or x2));
  97. w:=w or (((1-x2) or x1) xor ((1-x1) or x2));
  98. v1:=v1 shl 1;
  99. v2:=v2 shl 1;
  100. x1:=v1 shr 7;
  101. x2:=v2 shr 7;
  102. c:=c*(w or ((1-x2) or x1));
  103. d:=d*(w or ((1-x1) or x2));
  104. w:=w or (((1-x2) or x1) xor ((1-x1) or x2));
  105. v1:=v1 shl 1;
  106. v2:=v2 shl 1;
  107. x1:=v1 shr 7;
  108. x2:=v2 shr 7;
  109. c:=c*(w or ((1-x2) or x1));
  110. d:=d*(w or ((1-x1) or x2));
  111. w:=w or (((1-x2) or x1) xor ((1-x1) or x2));
  112. v1:=v1 shl 1;
  113. v2:=v2 shl 1;
  114. x1:=v1 shr 7;
  115. x2:=v2 shr 7;
  116. c:=c*(w or ((1-x2) or x1));
  117. d:=d*(w or ((1-x1) or x2));
  118. w:=w or (((1-x2) or x1) xor ((1-x1) or x2));
  119. a1:=((c xor 255) +1)*k+(1-k)*c;
  120. b1:=((d xor 255) +1)*k+(1-k)*d;
  121. otv:=(a1+b1)*(1-k)+(a-(a1+b1)+b)*k;
  122. writeln(ShortInt(ans)+otv*post);
  123. end.

Комментарии

Часть 2

Вторая часть кода (строки с 39 и до конца) решает задачу для чисел с одноименными знаками.
В c и d снова запишем a и b, которые "потерялись" там при работе первой части. В k определяем знак наших чисел. Если оба отрицательные, то 1. Оба +, то 0. Если же разноименные знаки, то k тоже 0, но для того чтобы отсечь этот случай заводим переменную post. Переменная sluch, для одноименных знаков даст 1, для разноименных 0. Таким образом в post будет 1, если знаки одноименные, и 0, если разноименные. (В дальнейшем мы умножим ответ второй части (переменная otv) на post. Если знаки разноименные, то ответ занулится, одноименные - останется.)
Ок, "защитили" себя от первой части кода, теперь можем спокойно искать максимальное число в рамках 2-ой части. Отрицательные числа будем сравнивать как положительные. Поясню: как я говорил в первой части, при преобразовании в Byte, отрицательного числа берется его дополнительный код, а в старший разряд записывается 1. Итак старшие разряды и для отрицательных и для положительных чисел равны. Так что достаточно сравнивать остальные разряды. Строки 44 и 45: если a и b положительные (k=0, 1-k=1), то оставляет числа, если отрицательные, то в c и d запишутся модули чисел.
В строке 46 формируется число. Если разряд этого числа в двоичной записи равен 1, то соответствующие разряды чисел c и d не совпадают.
В sum записывается дизъюнкция всех разрядов числа mask. Если sum равно 0, то числа a и b равны, если 1, то не равны.
Если числа равны, то одно из них надо занулить, так как в ответ берется сумма двух чисел. В строке 64 это и произойдет при равенстве чисел. При их различии (sum=1) в переменной v1 запишется число вида: разряд равен 1, если соответствующий разряд числа c больше соответствующего разряда числа b, 0, если меньше либо равен.
(Не грустим! Уже почти все=))
Далее 8 раз (для каждого разряда) следует конструкция вида:

  1. v1:=v1 shl 1;
  2. v2:=v2 shl 1;
  3. x1:=v1 shr 7;
  4. x2:=v2 shr 7;
  5. c:=c*(w or ((1-x2) or x1));
  6. d:=d*(w or ((1-x1) or x2));
  7. w:=w or (((1-x2) or x1) xor ((1-x1) or x2));

Суть в том, чтобы найти число с наибольшим не повторяющимся разрядом. Найдя его, оставить его нетронутым, другое число занулить, и при продолжении "игнорировать" остальные несовпадения разрядов.
В x1 и x2 получаем очередную пару разрядов. w отвечает за то, нашли мы различные разряды или нет. Если однажды нашли, то w станет 1 (((1-x2) or x1) xor ((1-x1) or x2) равно 1, если разные разряды, и 0, если одинаковые (можете проверить сами)), а число с разрядом 0, станет равным 0 ( число умножить на 1 минус разряд другого числа (1) or 0, т.е. 0) строки 74, 75, например. А потом, так как w=1, то число не будет меняться при дальнейшем его умножении. И само w, так как w:=w or что-то.
Если разряды разные, то числа c и d остаются неизменными ((1-x2) or x1)=1). Операцией shl убираем отработанные разряды.
Концовка!!!
В a1 и b1 снова формируем отрицательные числа, если они были на вводе (k=1), или оставляем положительные (k=0, 1-k=1).
В otv записываем сумму a1 и b1, если изначально были даны 2 неотрицательных числа (так как в этом случае одно из них мы занулили), или сумму 2-х исходных минус сумму a1 и b1, если на входе было 2 отрицательных числа. Так как в сумме a1 и b1 мы получили максимальное по модулю.
И наконец выводим ответ: сумма ответов на обе части (не забываем пeременную ans в тип ShortInt преобразовать, чтобы соответствовать нормам приличия=)), но второй ответ домножаем на post (почему? читай выше).
Итак, если изначально знаки были одноименными, то в ans будет 0, а в otv - ответ. Если разноименные, то в ans ответ а otv*post будет равно 0. Сложив их, получим ответ.

Часть 1

Буду разъяснять код по частям.
Сначала ввели наши a и b типа ShortInt. Знаки у этих чисел могут быть одноименные или разноименные. Так вот: 1-ая часть кода - для чисел с разноименными знаками. В конце этой части в переменной ans мы получим либо большее из этих чисел, либо 0, если знаки чисел были одноименные.
1-ая часть - это с 7-ой строчки по 38-ую.
Далее преобразуем наши переменные в тип Byte. Здесь следует учесть, что если мы преобразуем отрицательное число, то в Byte запишется дополнительный код, а в старший разряд запишется 1. (Например: Число -3. Двоичная запись: 10000011. Дополнительный код для типа ShortInt: 01111101. Преобразуем в Byte, получим: 11111101.) Если же преобразуем неотрицательное число, то все останется на местах. Так же заметим, что для неотрицательного числа самый старший разряд всегда будет равен 0, т.к. в ShortInt числа до 127.
Далее: в переменную k запишется 1, если старшие разряды c и d совпадают, т.е. знаки a и b - одноименные. Если же они разноименные, то в k запишется 0. Если k=1, то после выполнения строчек 11 и 12 старшие разряды c и d будут равны 1, если k=0, то разряды останутся без изменений.
Далее: блоки с 13 по 24 строку и с 25 по 36 - аналогичны.
Суть в том, чтобы отрицательное число превратить в 0, а неотрицательное оставить без изменений.
Для этого мы изменяем старший разряд. c1:=c xor 128; Если число было отрицательное, то его старший разряд после выполнения этой строки станет равен 0. Если положительное, то 1. Теперь вычленяем этот старший разряд и составляем число в переменной mak, каждый разряд которого равен этому старшему разряду. (т.е. либо 00000000, либо 11111111) Затем, выполнив побитовое умножение, получим либо 0 (если число было отрицательным), либо останется то же число.
Далее: в переменной ans записываем сумму полученных чисел(0 + неотрицательное число). НО теперь надо "затереть" старший разряд, так как при выполнении этой строки c1:=c xor 128; для положительного числа, его старший разряд станет 1. А ее изначально там не было.
Если же у нас k было равно 1, то наш кусок кода проработает с обоими числами как с отрицательными, т.е. оба они превратятся в нуль, и в ans запишется 0.
Теперь переходим ко 2-ой части. (откомментирую ее позже)