qwerty787788

CF1408I

Sep 30th, 2020
726
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.54 KB | None | 0 0
  1. import java.math.BigInteger;
  2. import java.util.*;
  3.  
  4. public class Test {
  5.     static class Diffs {
  6.         int[] a;
  7.  
  8.         public Diffs(int[] a) {
  9.             this.a = a;
  10.         }
  11.  
  12.         @Override
  13.         public boolean equals(Object o) {
  14.             if (this == o) return true;
  15.             if (o == null || getClass() != o.getClass()) return false;
  16.             Diffs diffs = (Diffs) o;
  17.             return Arrays.equals(a, diffs.a);
  18.         }
  19.  
  20.         @Override
  21.         public int hashCode() {
  22.             return Arrays.hashCode(a);
  23.         }
  24.  
  25.         @Override
  26.         public String toString() {
  27.             return "Diffs{" +
  28.                     "a=" + Arrays.toString(a) +
  29.                     '}';
  30.         }
  31.     }
  32.  
  33.     private static int[] solve(int[] numbers, int totRemoves, int maxPower) {
  34.         Map<Diffs, Integer> set = new HashMap<>();
  35.         int startXor = 0;
  36.         for (int cur : numbers) {
  37.             startXor ^= cur;
  38.             int[] a = new int[totRemoves + 1];
  39.             for (int i = 0; i < a.length; i++) {
  40.                 a[i] = cur ^ (cur - i);
  41.             }
  42.             Diffs diffs = new Diffs(a);
  43.             set.put(diffs, set.getOrDefault(diffs, 0) + 1);
  44.         }
  45.         final int n = 1 << maxPower;
  46.         int[][] dp = new int[totRemoves + 1][n]; // used, xor
  47.         dp[0][0] = 1;
  48.         for (Map.Entry<Diffs, Integer> entry : set.entrySet()) {
  49.             int[] canXor = entry.getKey().a;
  50.             int totalNumbersHere = entry.getValue();
  51.             for (int used = 0; used < dp.length; used++) {
  52.                 for (int xor = 0; xor < n; xor++) {
  53.                     int ways = dp[used][xor];
  54.                     if (ways == 0) {
  55.                         continue;
  56.                     }
  57.                     dp[used][xor] = 0;
  58.                     rec(totalNumbersHere, totRemoves, 1, used, dp, canXor, xor, ways);
  59.                 }
  60.             }
  61.         }
  62.         int[] res = new int[1 << maxPower];
  63.         for (int i = 0; i < n; i++) {
  64.             int ways = dp[dp.length - 1][i];
  65.             res[i ^ startXor] = ways;
  66.         }
  67.         int inv = BigInteger.valueOf(numbers.length).modInverse(BigInteger.valueOf(mod)).intValue();
  68.         int mulInv = 1;
  69.         for (int i = 0; i < totRemoves; i++) {
  70.             mulInv = mul(mulInv, inv);
  71.         }
  72.         for (int i = 0; i < res.length; i++) {
  73.             res[i] = mul(res[i], mulInv);
  74.         }
  75.         return res;
  76.     }
  77.  
  78.     public static void main123(String[] args) {
  79.         int totRems = 16;
  80.         long START = System.currentTimeMillis();
  81.         Random rnd = new Random(123);
  82.         final int n = 1 << totRems;
  83.         int[] a = new int[n];
  84.         for (int i = 0; i < n; i++) {
  85.             int max = (1 << totRems) - totRems;
  86.             a[i] = rnd.nextInt(max) + totRems;
  87.         }
  88.         precC();
  89.         int[] foo = solve(a, totRems, totRems);
  90.         System.err.println("OK! " + (System.currentTimeMillis() - START));
  91.     }
  92.  
  93.     public static void main(String[] args) {
  94.         precC();
  95.         Scanner in = new Scanner(System.in);
  96.         int nums = in.nextInt();
  97.         int totRemoves = in.nextInt();
  98.         int maxPower = in.nextInt();
  99.         int[] a = new int[nums];
  100.         for (int i = 0; i < nums; i++) {
  101.             a[i] = in.nextInt();
  102.         }
  103.         int[] res = solve(a, totRemoves, maxPower);
  104.         for (int r : res) {
  105.             System.out.print(r + " ");
  106.         }
  107.     }
  108.  
  109.     static int[][] c;
  110.  
  111.     static void precC() {
  112.         c = new int[(1 << 16) + 5][18];
  113.         c[0][0] = 1;
  114.         for (int i = 1; i < c.length; i++) {
  115.             c[i][0] = 1;
  116.             for (int j = 1; j < c[i].length; j++) {
  117.                 c[i][j] = add(c[i - 1][j - 1], c[i - 1][j]);
  118.             }
  119.         }
  120.     }
  121.  
  122.     static void rec(int totNums, int maxN, int curX, int alrUsed, int[][] dp, int[] xors, int nowXor, int ways) {
  123.         if (curX + alrUsed > maxN) {
  124.             dp[alrUsed][nowXor] = add(dp[alrUsed][nowXor], ways);
  125.             return;
  126.         }
  127.         for (int cnt = 0; cnt * curX + alrUsed <= maxN && cnt <= totNums; cnt++) {
  128.             int nextXor = nowXor ^ ((cnt & 1) * xors[curX]);
  129.             int nways = mul(c[totNums][cnt], ways);
  130.             rec(totNums - cnt, maxN, curX + 1, alrUsed + cnt * curX, dp, xors, nextXor, nways);
  131.         }
  132.     }
  133.  
  134.     static int mul(int x, int y) {
  135.         return (int) (x * 1L * y % mod);
  136.     }
  137.  
  138.     final static int mod = 998244353;
  139.  
  140.     static int add(int x, int y) {
  141.         x += y;
  142.         return x >= mod ? (x - mod) : x;
  143.     }
  144. }
  145.  
Advertisement
Add Comment
Please, Sign In to add comment