qwerty787788

Karatsuba FBHC

Jan 31st, 2016
264
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.66 KB | None | 0 0
  1. import java.io.*;
  2. import java.math.BigInteger;
  3. import java.util.*;
  4. import java.util.concurrent.*;
  5. import java.util.concurrent.atomic.AtomicInteger;
  6.  
  7. public class E {
  8.     FastScanner in;
  9.     PrintWriter out;
  10.  
  11.     void run() {
  12.         try {
  13.             in = new FastScanner(new File("transportation.txt"));
  14.             out = new PrintWriter(new File("E.out"));
  15.  
  16.             solve();
  17.  
  18.             out.close();
  19.         } catch (FileNotFoundException e) {
  20.             e.printStackTrace();
  21.         }
  22.     }
  23.  
  24.     void solve() {
  25.         fact = new long[MAX];
  26.         factInv = new long[MAX];
  27.         fact[0] = 1;
  28.         for (int i = 1; i < MAX; i++) {
  29.             fact[i] = i * 1L * fact[i - 1] % mod;
  30.         }
  31.         BigInteger MOD = BigInteger.valueOf(mod);
  32.         for (int i = 0; i < MAX; i++) {
  33.             factInv[i] = BigInteger.valueOf(fact[i]).modInverse(MOD).intValue();
  34.         }
  35.          solve(1, Integer.MAX_VALUE, 4);
  36. //      solve(2, 2, 1);
  37.     }
  38.  
  39.     long c(int n, int k) {
  40.         if (k < 0 || k > n) {
  41.             return 0;
  42.         }
  43.         long res = fact[n] * factInv[k] % mod * factInv[n - k] % mod;
  44.         return res;
  45.     }
  46.  
  47.     final int MAX = 500000 + 100;
  48.     long[] fact;
  49.     long[] factInv;
  50.  
  51.     final int mod = (int) 1e9 + 7;
  52.     final long mod2 = mod * 1L * mod;
  53.     final int C = 10;
  54.  
  55.     long[] mult(long[] a, long[] b) {
  56.  
  57.         long[] res = new long[a.length + b.length - 1];
  58.         int n = a.length;
  59.         if (b.length != n) {
  60.             throw new AssertionError();
  61.         }
  62.         if (n <= C) {
  63.             for (int i = 0; i < n; i++) {
  64.                 for (int j = 0; j < n; j++) {
  65.                     res[i + j] += a[i] * 1L * b[j];
  66.                     if (res[i + j] >= mod2) {
  67.                         res[i + j] -= mod2;
  68.                     }
  69.                 }
  70.             }
  71.         } else {
  72.             int mid = n / 2;
  73.             long[] aLeft = new long[mid];
  74.             long[] aRight = new long[n - mid];
  75.             long[] bLeft = new long[mid];
  76.             long[] bRight = new long[n - mid];
  77.             for (int i = 0; i < mid; i++) {
  78.                 aLeft[i] = a[i];
  79.                 bLeft[i] = b[i];
  80.             }
  81.             for (int i = 0; i < n - mid; i++) {
  82.                 aRight[i] = a[i + mid];
  83.                 bRight[i] = b[i + mid];
  84.             }
  85.             long[] Q = mult(aLeft, bLeft);
  86.             long[] W = mult(aRight, bRight);
  87.             long[] tmpA = new long[Math.max(aLeft.length, aRight.length)];
  88.             long[] tmpB = new long[tmpA.length];
  89.             for (int i = 0; i < aLeft.length; i++) {
  90.                 tmpA[i] = aLeft[i];
  91.                 tmpB[i] = bLeft[i];
  92.             }
  93.             for (int i = 0; i < aRight.length; i++) {
  94.                 tmpA[i] += aRight[i];
  95.                 tmpB[i] += bRight[i];
  96.                 if (tmpA[i] >= mod) {
  97.                     tmpA[i] -= mod;
  98.                 }
  99.                 if (tmpB[i] >= mod) {
  100.                     tmpB[i] -= mod;
  101.                 }
  102.             }
  103.             long[] E = mult(tmpA, tmpB);
  104.             for (int i = 0; i < E.length; i++) {
  105.                 if (i < Q.length) {
  106.                     E[i] -= Q[i];
  107.                     if (E[i] < 0) {
  108.                         E[i] += mod;
  109.                     }
  110.                 }
  111.                 if (i < W.length) {
  112.                     E[i] -= W[i];
  113.                     if (E[i] < 0) {
  114.                         E[i] += mod;
  115.                     }
  116.                 }
  117.             }
  118.             for (int i = 0; i < Q.length; i++) {
  119.                 res[i] = Q[i];
  120.             }
  121.             for (int i = 0; i < E.length; i++) {
  122.                 res[i + mid] += E[i];
  123.                 if (res[i + mid] >= mod) {
  124.                     res[i + mid] -= mod;
  125.                 }
  126.             }
  127.             for (int i = 0; i < W.length; i++) {
  128.                 res[i + mid + mid] += W[i];
  129.                 if (res[i + mid + mid] >= mod) {
  130.                     res[i + mid + mid] -= mod;
  131.                 }
  132.             }
  133.         }
  134.         for (int i = 0; i < res.length; i++) {
  135.             res[i] %= mod;
  136.         }
  137.         return res;
  138.     }
  139.  
  140.     class Testcase implements Callable<Testcase> {
  141.         int test;
  142.         long result;
  143.  
  144.         Testcase(int test) {
  145.             this.test = test;
  146.         }
  147.  
  148.         int n, k, l;
  149.         long[] pos;
  150.  
  151.         void readInput() {
  152.             n = in.nextInt();
  153.             k = in.nextInt();
  154.             l = in.nextInt();
  155.             String s = in.next();
  156.             pos = new long[n];
  157.             n = 0;
  158.             for (int i = 0; i < s.length(); i++) {
  159.                 if (s.charAt(i) == '1') {
  160.                     pos[n++] = i;
  161.                 }
  162.             }
  163.         }
  164.  
  165.         void solve() {
  166.             BigInteger MOD = BigInteger.valueOf(mod);
  167.             if (k == n - 1) {
  168.                 result = l * 1L
  169.                         * BigInteger.valueOf(4).modInverse(MOD).intValue()
  170.                         % mod;
  171.                 return;
  172.             }
  173.             long[] posRev = new long[n];
  174.             for (int i = 0; i < n; i++) {
  175.                 posRev[i] = pos[n - 1 - i];
  176.             }
  177.             long[] mul = mult(pos, posRev);
  178.             long[] avDist = new long[n + 1];
  179.             long sum2 = 0, sum2shift = 0;
  180.             for (int i = 0; i < n; i++) {
  181.                 sum2 += pos[i] * pos[i];
  182.                 sum2 %= mod;
  183.             }
  184.             long sum = 0;
  185.             sum2shift = sum2;
  186.             long[] pos2 = new long[n + n];
  187.             for (int i = 0; i < n; i++) {
  188.                 pos2[i] = pos[i];
  189.                 pos2[i + n] = pos[i] + l;
  190.             }
  191.             pos = pos2;
  192.             for (int d = 1; d < n; d++) {
  193.                 sum2shift -= pos[d - 1] * pos[d - 1];
  194.                 sum2shift += pos[n + d - 1] * pos[n + d - 1];
  195.                 sum2shift %= mod;
  196.                 sum += pos[n - d];
  197.                 sum %= mod;
  198.                 long tmp1 = mul[n - d - 1];
  199.                 long myMul = tmp1;
  200.                 long tmp2 = mul[2 * n - 1 - d];
  201.                 myMul += tmp2 + sum * l;
  202.                 myMul %= mod;
  203.                 avDist[d] = sum2 + sum2shift - 2 * myMul;
  204.                 avDist[d] %= mod;
  205.                 if (avDist[d] < 0) {
  206.                     avDist[d] += mod;
  207.                 }
  208.             }
  209.             long total = c(n, k);
  210.             for (int d = 1; d < n; d++) {
  211.                 int needRem = k - (d - 1);
  212.                 if (needRem < 0) {
  213.                     break;
  214.                 }
  215.                 long now = c(n - 2 - d + 1, needRem);
  216.                 result += now * avDist[d] % mod
  217.                         * BigInteger.valueOf(4).modInverse(MOD).intValue()
  218.                         % mod;
  219.                 result %= mod;
  220.             }
  221.             result = result
  222.                     * BigInteger.valueOf(total).modInverse(MOD).intValue()
  223.                     % mod;
  224.             result = result * BigInteger.valueOf(l).modInverse(MOD).intValue()
  225.                     % mod;
  226.         }
  227.  
  228.         @Override
  229.         public Testcase call() throws Exception {
  230.             System.err.println("start doing test #" + test);
  231.             solve();
  232.             int total = testDone.addAndGet(1);
  233.             System.err.println("done test #" + test + " (result = " + result
  234.                     + "), total " + total + "/" + tc + " tests done in "
  235.                     + (System.currentTimeMillis() - START_TIME) + " ms");
  236.             return this;
  237.         }
  238.  
  239.         public void writeOutput() {
  240.             out.println("Case #" + test + ": " + result);
  241.             out.flush();
  242.         }
  243.  
  244.     }
  245.  
  246.     long START_TIME;
  247.     int tc;
  248.     AtomicInteger testDone = new AtomicInteger();
  249.  
  250.     void solve(int testFrom, int testTo, int numThreads) {
  251.         START_TIME = System.currentTimeMillis();
  252.         tc = in.nextInt();
  253.         List<Future<Testcase>> tests = new ArrayList<Future<Testcase>>();
  254.         ExecutorService pool = Executors.newFixedThreadPool(numThreads);
  255.         for (int t = 0; t < tc; t++) {
  256.             Testcase test = new Testcase(t + 1);
  257.             test.readInput();
  258.             if (t + 1 >= testFrom && t + 1 <= testTo) {
  259.                 tests.add(pool.submit(test));
  260.             }
  261.         }
  262.         for (Future<Testcase> test : tests) {
  263.             try {
  264.                 Testcase testcase = test.get();
  265.                 testcase.writeOutput();
  266.             } catch (InterruptedException e) {
  267.                 throw new RuntimeException(e);
  268.             } catch (ExecutionException e) {
  269.                 throw new RuntimeException(e);
  270.             }
  271.         }
  272.         pool.shutdown();
  273.         System.err.println("all in "
  274.                 + (System.currentTimeMillis() - START_TIME) + " ms");
  275.     }
  276.  
  277.     class FastScanner {
  278.         BufferedReader br;
  279.         StringTokenizer st;
  280.  
  281.         public FastScanner(File f) {
  282.             try {
  283.                 br = new BufferedReader(new FileReader(f));
  284.             } catch (FileNotFoundException e) {
  285.                 e.printStackTrace();
  286.             }
  287.         }
  288.  
  289.         public FastScanner(InputStream f) {
  290.             br = new BufferedReader(new InputStreamReader(f));
  291.         }
  292.  
  293.         String next() {
  294.             while (st == null || !st.hasMoreTokens()) {
  295.                 String s = null;
  296.                 try {
  297.                     s = br.readLine();
  298.                 } catch (IOException e) {
  299.                     e.printStackTrace();
  300.                 }
  301.                 if (s == null)
  302.                     return null;
  303.                 st = new StringTokenizer(s);
  304.             }
  305.             return st.nextToken();
  306.         }
  307.  
  308.         boolean hasMoreTokens() {
  309.             while (st == null || !st.hasMoreTokens()) {
  310.                 String s = null;
  311.                 try {
  312.                     s = br.readLine();
  313.                 } catch (IOException e) {
  314.                     e.printStackTrace();
  315.                 }
  316.                 if (s == null)
  317.                     return false;
  318.                 st = new StringTokenizer(s);
  319.             }
  320.             return true;
  321.         }
  322.  
  323.         int nextInt() {
  324.             return Integer.parseInt(next());
  325.         }
  326.  
  327.         long nextLong() {
  328.             return Long.parseLong(next());
  329.         }
  330.  
  331.         double nextDouble() {
  332.             return Double.parseDouble(next());
  333.         }
  334.     }
  335.  
  336.     public static void main(String[] args) {
  337.         new E().run();
  338.     }
  339. }
Advertisement
Add Comment
Please, Sign In to add comment