码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round 449 Div. 1

时间:2017-12-04 19:18:21      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:intval   ++   vmax   ever   sum   reverse   token   imp   false   

problem A link

problem B link

problem C link

problem D link

首先枚举vip的数量$x$,那么首先需要为这$x$选取$x$个位置,为$C_{n}^{x}$。剩下的$n-x$是50和100的个数。

设$f(n,L,R)$表示$n$个50和100,最后剩余50的个数为$[L,R]$范围,满足这些的合法顺序的方案数。那么答案为:$answer=\sum_{i=0}^{n}C_{n}^{i}f(n-i,L,R)$

现在考虑如何计算$f(n,L,R)$。

首先假设$n$中50和100的个数相等的答案,即$f(n,0,0),n$为偶数。这样的合法序列可以看作一条从$(0,0)$到$(n,0)$的折线,从$(x_{i},y_{i})$到$(x_{i}+1,y_{i+1})$时,需满足$|y_{i}-y_{i+1}|=1$且$y_{i}\ge 0,y_{i+1}\ge 0$。所有的情况有$C_{n}^{\frac{2}{2}}$个。但是这些中有不合法的情况。假设这条折线在$(x_{t},y_{t})$时第一次出现$y_{t}<0$的情况,即$y_{t}=-1$。现在将$(0,0)$到$x_{t},y_{t}$之间的折线部分按照直线$y=-1$作一个对称,那么现在的折线变成了从点$(0,-2)$到点$(n,0)$。那么所有的从$(0,0)$到$(n,0)$的不合法的折线都会对应到一条从$(0,-2)$到点$(n,0)$的折线。而从$(0,-2)$到点$(n,0)$折线有$C_{n}^{\frac{n}{2}-1}$种(因为要选择$\frac{n}{2}-1$条向下)。所以$f(n,0,0)=C_{n}^{\frac{n}{2}}-C_{n}^{\frac{n}{2}-1}$。

problem E link

code for problem A

import java.util.Scanner;

public class Main {

  String s = "What are you doing at the end of the world? Are you busy? Will you save us?";
  String A = "What are you doing while sending \"";
  String B = "\"? Are you busy? Will you send \"";
  String C = "\"?";

  long[] f = new long[61];

  public static void main(String[] args) {

    new Main().cal();


  }

  void cal() {
    f[0] = s.length();
    int t = A.length() + B.length() + C.length();
    for (int i = 1; i <= 60; ++ i) {
      f[i] = f[i - 1] * 2 + t;
    }
    Scanner in = new Scanner(System.in);
    StringBuilder sb = new StringBuilder();
    int q = in.nextInt();
    for (int i = 0; i < q; ++ i) {
      int n = in.nextInt();
      long k = in.nextLong();
      sb.append(get(n, k));
    }
    System.out.println(sb.toString());
  }
  char get(int n, Long k) {
    int t = A.length();
    while (n > 54) {
      if (k <= t) {
        return A.charAt(k.intValue() - 1);
      }
      k -= t;
      n -= 1;
    }
    if (k > f[n]) {
      return ‘.‘;
    }
    while (n > 0) {
      if (k <= A.length()) {
        return A.charAt(k.intValue() - 1);
      }
      k -= A.length();
      if (f[n - 1] >= k) {
        n -= 1;
        continue;
      }
      k -= f[n - 1];
      if (k <= B.length()) {
        return B.charAt(k.intValue() - 1);
      }
      k -= B.length();
      if (f[n - 1] >= k) {
        n -= 1;
        continue;
      }
      k -= f[n - 1];
      return C.charAt(k.intValue() - 1);
    }
    return s.charAt(k.intValue() - 1);
  }
}

  

code for problem B

import java.util.Scanner;

public class Main {

  public static void main(String[] args) {
    new Main().cal();
  }

  int n;
  int m;
  int c;
  int[] p = null;

  void cal() {
    Scanner in = new Scanner(System.in);
    n = in.nextInt();
    m = in.nextInt();
    c = in.nextInt();
    p = new int[n];
    for (int i = 0; i < m; ++ i) {
      int x = in.nextInt();
      int pos = add(x);
      p[pos] = x;
      System.out.println(pos + 1);
      System.out.flush();
      if (finish()) {
        return;
      }
    }
  }

  int add(int x) {
    if (x <= c / 2) {
      int id = 0;
      while (p[id] != 0 && p[id] <= x) {
        id ++;
      }
      return id;
    }
    else {
      int id = n - 1;
      while (p[id] != 0 && p[id] >= x) {
        id --;
      }
      return id;
    }
  }

  boolean finish() {
    for (int i = 0; i < n; ++ i) {
      if (p[i] == 0) {
        return false;
      }
    }
    return true;
  }

}

  

code for problem C

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Main {

  public static void main(String[] args) {
    new Main().cal();
  }

  static class Pair {
    long val;
    int cnt;

    Pair() {}
    Pair(long val, int cnt) {
      this.val = val;
      this.cnt = cnt;
    }
  }

  static class PairComparator implements Comparator<Pair> {
    @Override
    public int compare(Pair a, Pair b) {
      return a.val < b.val ? -1 : 1;
    }
  }

  int n;
  int m;
  int seed;
  int vmax;
  Pair[] b = null;
  Pair[] c = null;
  int bSize = 0;
  int cSize = 0;

  int rnd() {
    int ret = seed;
    seed = (int)((seed * 7L + 13) % 1000000007);
    return ret;
  }



  void cal() {
    Scanner in = new Scanner(System.in);
    n = in.nextInt();
    m = in.nextInt();
    seed = in.nextInt();
    vmax = in.nextInt();

    b = new Pair[n];
    c = new Pair[n];

    b[bSize ++] = new Pair(rnd() % vmax + 1, 1);
    for (int i = 2; i <= n; ++ i) {
      int val = rnd() % vmax + 1;
      if (val == b[bSize - 1].val) {
        b[bSize - 1].cnt += 1;
      }
      else {
        b[bSize ++] = new Pair(val, 1);
      }
    }

    for (int i = 0; i < m; ++ i) {
      int op = rnd() % 4 + 1;
      int left = rnd() % n + 1;
      int right = rnd() % n + 1;

      if (left > right) {
        int tmp = left;
        left = right;
        right = tmp;
      }

      int x = 0;
      int y = 0;

      if (op == 3) {
        x = rnd() % (right - left + 1) + 1;
      }
      else {
        x = rnd() % vmax + 1;
      }
      if (op == 4) {
        y = rnd() % vmax + 1;
      }

      if (op == 1 || op == 2) {
        operation1or2(left, right, x, op == 1);
      }
      else if (op == 3) {
        operation3(left, right, x);
      }
      else  {
        operation4(left, right, x, y);
      }
    }
  }

  void operation1or2(int left, int right, int x, boolean isOperation1) {
    int L = 0, R = 0;
    cSize = 0;
    for (int i = 0; i < bSize; ++ i) {
      L = R + 1;
      R = L + b[i].cnt - 1;
      add(b[i].val, intersect(L, left - 1, L, R));
      if (isOperation1) {
        add(b[i].val + x, intersect(left, right , L, R));
      }
      else {
        add(x, intersect(left, right , L, R));
      }

      add(b[i].val, intersect(right + 1, R, L, R));
    }
    for (int i = 0; i <  cSize; ++ i) {
      b[i] = c[i];
    }
    bSize = cSize;
  }
  void operation3(int left, int right, int kth) {
    int L = 0, R = 0;
    cSize = 0;
    for (int i = 0; i < bSize; ++ i) {
      L = R + 1;
      R = L + b[i].cnt - 1;
      int cnt = intersect(left, right , L, R);
      if (cnt > 0) {
        c[cSize ++] = new Pair(b[i].val, cnt);
      }
    }
    Arrays.sort(c, 0, cSize, new PairComparator());
    for (int i = 0; i < cSize; ++ i) {
      if (c[i].cnt >= kth) {
        System.out.println(c[i].val);
        return;
      }
      kth -= c[i].cnt;
    }

  }

  void operation4(int left, int right, int x, int y) {
    int L = 0, R = 0;

    long result = 0;

    for (int i = 0; i < bSize; ++ i) {
      L = R + 1;
      R = L + b[i].cnt - 1;
      int cnt = intersect(left, right , L, R);
      if (cnt > 0) {
        result += Pow(b[i].val, x, y) * cnt % y;
        result %= y;
      }
    }
    System.out.println(result);
  }

  int intersect(int left1, int right1, int left2, int right2) {
    int left = Math.max(left1, left2);
    int right = Math.min(right1, right2);
    return Math.max(0, right - left + 1);
  }

  void add(long val, int cnt) {
    if (cnt == 0) {
      return;
    }
    if (cSize > 0 && c[cSize - 1].val == val) {
      c[cSize - 1].cnt += cnt;
    }
    else {
      c[cSize ++] = new Pair(val, cnt);
    }
  }

  static long Pow(long a, int b, int mod) {
    long result = 1;
    a %= mod;
    while (b != 0) {
      if (b % 2 == 1) {
        result = result * a % mod;
      }
      a = a * a % mod;
      b >>= 1;
    }
    return result;
  }

}

  

code for problem D

import java.util.*;

public class Main {

  public static void main(String[] args) {
    new Main().cal();
  }

  int n;
  int p;
  int left;
  int right;
  long[] fact = null;
  int[] primes = null;

  void init() {
    primes = split(p);
    fact = new long[n + 1];
    fact[0] = 1;
    for (int i = 1; i <= n; ++ i) {
      int k = i;
      for (int prime : primes) {
        while (k % prime == 0) {
          k /= prime;
        }
      }
      fact[i] = fact[i - 1] * k % p;
    }
  }



  void cal() {
    Scanner in = new Scanner(System.in);
    n = in.nextInt();
    p = in.nextInt();
    left = in.nextInt();
    right = in.nextInt();
    if (p == 1) {
      System.out.println(0);
      return;
    }
    init();

    long result = 0;
    for (int cNum = 0; cNum <= n; ++ cNum) {
      long t = calculate(cNum, (cNum + left + 1) / 2) - calculate(cNum, (cNum + right) / 2 + 1);
      t %= p;
      t *= calculate(n, cNum);
      t %= p;
      result += t;
      result %= p;
    }
    if (result < 0) {
      result += p;
    }
    System.out.println(result);
  }

  long calculate(int n, int m) {
    if (m < 0 || m > n) {
      return 0;
    }
    if (m == 0 || m == n) {
      return 1;
    }
    long result = fact[n] * reverse(fact[m] * fact[n - m] % p, p) % p;
    for (int prime : primes) {
      int cnt = count(n, prime) - count(m, prime) - count(n - m, prime);
      result = result * Pow(prime, cnt, p) % p;
    }
    return result;
  }

  static int count(int n, int p) {
    int cnt = 0;
    while (n > 0) {
      cnt += n / p;
      n /= p;
    }
    return cnt;
  }

  static long Pow(long a, long b, long mod) {
    long result = 1;
    while (b > 0) {
      if (b % 2 == 1) {
        result = result * a % mod;
      }
      a = a * a % mod;
      b >>= 1;
    }
    return result;
  }

  static long reverse(long a, long b)
  {
    long[] r = exGcd(a,b);
    return (r[1] % b + b) % b;
  }

  static long[] exGcd(long a,long b)
  {
    if (b == 0)
    {
      return new long[]{a, 1, 0};
    }
    long[] result = exGcd(b, a % b);
    return new long[]{result[0], result[2], result[1] - a / b * result[2]};
  }

  static int[] split(int x) {
    List<Integer> list = new ArrayList<>();
    for (int i = 2; i * i <= x; ++ i) {
      if (x % i == 0) {
        list.add(i);
        while (x % i == 0) {
          x /= i;
        }
      }
    }
    if (x > 1) {
      list.add(x);
    }
    int[] result = new int[list.size()];
    for (int i = 0; i < list.size(); ++ i) {
      result[i] = list.get(i);
    }
    return result;
  }

}

code for problem E

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;


public class Main {

  public static void main(String[] args) {
    new Main();
  }

  static class FastIO {
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter out = new PrintWriter(System.out);
    StringTokenizer st = null;

    String nextToken() {
      while (st == null || !st.hasMoreTokens()) {
        try {
          st = new StringTokenizer(bufferedReader.readLine());
        }
        catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
      return st.nextToken();
    }
    int nextInt() {
      return Integer.parseInt(nextToken());
    }

    void output(Object object) {
      out.println(object);
    }

    void finish() {
      out.close();
    }

  }

  FastIO fastIO = new FastIO();


  Main() {
    cal();
    fastIO.finish();
  }

  static class Block {
    int nMin;
    int nMax;
    int left;
    int right;
    int off;
    int[] parent = null;
    int[] c = null;

    Block(int left, int right, int[] a) {
      this.left = left;
      this.right = right;
      this.off = 0;
      nMin = 1;
      nMax = Integer.MIN_VALUE;
      for (int i = left; i <= right; ++ i) {
        nMax = Math.max(nMax, a[i]);
      }
      parent = new int[nMax + 1];
      c = new int[nMax + 1];
      for (int i = left; i <= right; ++ i) {
        c[a[i]] += 1;
      }
      for (int i = 0; i < nMax + 1; ++ i) {
        parent[i] = i;
      }
    }
    int getRoot(int x) {
      if (parent[x] != x) {
        parent[x] = getRoot(parent[x]);
      }
      return parent[x];
    }
    void rebuild(int L, int R, int[] a, int x) {
      if (L == left && R == right) {
        rebuildAll(x);
        return;
      }
      for (int i = left; i <= right; ++ i) {
        a[i] = getRoot(a[i]);
      }
      for (int i = L; i <= R; ++ i) {
        if (a[i] - off > x) {
          c[a[i]] -= 1;
          a[i] -= x;
          c[a[i]] += 1;
        }
      }
    }
    void rebuildAll(int x) {
      if (nMax - nMin + 1 <= x) {
        return;
      }
      if (nMin + x + x - 1 <= nMax) {
        off += x;
        for (int i = nMin; i < nMin + x; ++ i) {
          parent[i] = i + x;
          c[i + x] += c[i];
          c[i] = 0;
        }
        nMin += x;
      }
      else {
        for (int i = nMin + x; i <= nMax; ++ i) {
          parent[i] = i - x;
          c[i - x] += c[i];
          c[i] = 0;
        }
        nMax = nMin + x - 1;
      }
    }
    int query(int L, int R, int[] a, int x) {
      if (L == left && R == right) {
        return queryAll(x);
      }
      x += off;
      int cnt = 0;
      for (int i = L; i <= R; ++ i) {
        if (getRoot(a[i]) == x) {
          cnt += 1;
        }
      }
      return cnt;
    }
    int queryAll(int x) {
      if (nMin <= x + off && x + off <= nMax) {
        return c[x + off];
      }
      return 0;
    }
  }

  static final int BLOCK_SIZE = 333;

  int n;
  int m;
  int[] a = null;
  Block[] b = null;

  void cal() {

    n = fastIO.nextInt();
    m = fastIO.nextInt();
    a = new int[n];
    for (int i = 0; i < n; ++ i) {
      a[i] = fastIO.nextInt();
    }
    final int nBlockNum = (n - 1) / BLOCK_SIZE + 1;
    b = new Block[nBlockNum];
    for (int i = 0; i < nBlockNum; ++ i) {
      int left = i * BLOCK_SIZE;
      int right = Math.min(n - 1, left + BLOCK_SIZE - 1);
      b[i] = new Block(left, right, a);
    }
    for (int i = 0; i < m; ++ i) {
      int op = fastIO.nextInt();
      int left = fastIO.nextInt() - 1;
      int right = fastIO.nextInt() - 1;
      int x = fastIO.nextInt();
      int lBlockIndex = left / BLOCK_SIZE;
      int rBlockIndex = right / BLOCK_SIZE;
      if (op == 1) {
        if (lBlockIndex == rBlockIndex) {
          b[lBlockIndex].rebuild(left, right, a, x);
        }
        else {
          b[lBlockIndex].rebuild(left, b[lBlockIndex].right, a, x);
          b[rBlockIndex].rebuild(b[rBlockIndex].left, right, a, x);
          for (int j = lBlockIndex + 1; j <= rBlockIndex - 1; ++ j) {
            b[j].rebuildAll(x);
          }
        }
      }
      else {
        int result = 0;
        if (lBlockIndex == rBlockIndex) {
          result += b[lBlockIndex].query(left, right, a, x);
        }
        else {
          result += b[lBlockIndex].query(left, b[lBlockIndex].right, a, x);
          result += b[rBlockIndex].query(b[rBlockIndex].left, right, a, x);
          for (int j = lBlockIndex + 1; j <= rBlockIndex - 1; ++ j) {
            result += b[j].queryAll(x);
          }
        }
        fastIO.output(result);
      }
    }
  }

}

  

Codeforces Round 449 Div. 1

标签:intval   ++   vmax   ever   sum   reverse   token   imp   false   

原文地址:http://www.cnblogs.com/jianglangcaijin/p/7977991.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!