/FB2012_Round2_3_SequenceSlicing/Petr06.java

https://github.com/lantoli/Google-Code-Jam · Java · 161 lines · 146 code · 11 blank · 4 comment · 28 complexity · 5b096c858df8df90c558ad0db0c500d8 MD5 · raw file

  1. import java.io.BufferedReader;
  2. import java.io.FileInputStream;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.InputStreamReader;
  7. import java.io.OutputStream;
  8. import java.io.PrintWriter;
  9. import java.math.BigInteger;
  10. import java.util.StringTokenizer;
  11. /**
  12. * Built using CHelper plug-in
  13. * Actual solution is at the top
  14. */
  15. public class Petr06 {
  16. public static void main(String[] args) {
  17. InputStream inputStream;
  18. try {
  19. inputStream = new FileInputStream("sample.in");
  20. } catch (IOException e) {
  21. throw new RuntimeException(e);
  22. }
  23. OutputStream outputStream;
  24. try {
  25. outputStream = new FileOutputStream("sample.out");
  26. } catch (IOException e) {
  27. throw new RuntimeException(e);
  28. }
  29. InputReader in = new InputReader(inputStream);
  30. PrintWriter out = new PrintWriter(outputStream);
  31. Sequence06 solver = new Sequence06();
  32. int testCount = Integer.parseInt(in.next());
  33. for (int i = 1; i <= testCount; i++) {
  34. solver.solve(i, in, out);
  35. }
  36. out.close();
  37. }
  38. }
  39. class Sequence06 {
  40. public void solve(int testNumber, InputReader in, PrintWriter out) {
  41. System.err.println(testNumber);
  42. long startTime = System.currentTimeMillis();
  43. int n = in.nextInt();
  44. long k = in.nextLong();
  45. long r = in.nextLong();
  46. long[] s = new long[n];
  47. for (int i = 0; i < n; ++i) {
  48. s[i] = in.nextLong();
  49. }
  50. if (k == 1) {
  51. out.println("Case #" + testNumber + ": 1/1");
  52. return;
  53. }
  54. long[] prevRep = new long[n];
  55. for (int i = 0; i < n; ++i) {
  56. prevRep[i] = Long.MAX_VALUE;
  57. for (int j = 0; j < n; ++j) {
  58. long delta = s[j] - s[i];
  59. if (delta < 0 || delta % n != 0) {
  60. continue;
  61. }
  62. delta /= n;
  63. if (delta == 0 && j >= i) {
  64. continue;
  65. }
  66. prevRep[i] = Math.min(prevRep[i], n - j + (delta - 1) * n + i);
  67. }
  68. }
  69. long res = 0;
  70. for (int start = 0; start < n; ++start) {
  71. long[] rotRep = new long[n];
  72. for (int i = 0; i < n; ++i) {
  73. rotRep[i] = prevRep[(start + i) % n];
  74. }
  75. long left = 0;
  76. long right = r + 10;
  77. if (getCount(rotRep, right) < k) {
  78. continue;
  79. }
  80. while (right - left > 1) {
  81. long middle = (left + right) / 2;
  82. if (getCount(rotRep, middle) < k) {
  83. left = middle;
  84. } else {
  85. right = middle;
  86. }
  87. }
  88. res += sumFrom(r - start - right + 2, n);
  89. }
  90. long p = 2 * res;
  91. long q = (r + 1) * (r + 1);
  92. long g = BigInteger.valueOf(p).gcd(BigInteger.valueOf(q)).longValue();
  93. out.println("Case #" + testNumber + ": " + p / g + "/" + q / g);
  94. System.err.println(System.currentTimeMillis() - startTime);
  95. }
  96. private long getCount(long[] prevRep, long cnt) {
  97. long n = prevRep.length;
  98. long res = 0;
  99. for (int i = 0; i < n; ++i) {
  100. long first = i;
  101. long last = cnt - 1;
  102. if (last < first) {
  103. continue;
  104. }
  105. last -= (last - i) % n;
  106. if (last % n != i) {
  107. throw new RuntimeException();
  108. }
  109. if (prevRep[i] < Long.MAX_VALUE) {
  110. last = Math.min(last, first + n * ((prevRep[i] - i + n - 1) / n - 1));
  111. }
  112. if (last < first) {
  113. continue;
  114. }
  115. res += (last - first) / n + 1;
  116. }
  117. return res;
  118. }
  119. private long sumFrom(long start, long n) {
  120. if (start <= 0) {
  121. return 0;
  122. }
  123. long cnt = start / n + 1;
  124. return (start + (start - (cnt - 1) * n)) * cnt / 2;
  125. }
  126. }
  127. class InputReader {
  128. private final BufferedReader reader;
  129. private StringTokenizer tokenizer;
  130. public InputReader(InputStream stream) {
  131. reader = new BufferedReader(new InputStreamReader(stream));
  132. tokenizer = null;
  133. }
  134. public String next() {
  135. while (tokenizer == null || !tokenizer.hasMoreTokens()) {
  136. try {
  137. tokenizer = new StringTokenizer(reader.readLine());
  138. } catch (IOException e) {
  139. throw new RuntimeException(e);
  140. }
  141. }
  142. return tokenizer.nextToken();
  143. }
  144. public int nextInt() {
  145. return Integer.parseInt(next());
  146. }
  147. public long nextLong() {
  148. return Long.parseLong(next());
  149. }
  150. }