「題解」Codeforces 785D

題目

CF785D

題解

枚舉左括號,計算它左邊都是左括號右邊都是右括號的複合要求的個數。

當枚舉到一個左括號時設此左括號的左邊有 \(n\) 個左括號,右邊有 \(m\) 個右括號則要算的是 \(\sum\limits_{i = 0}^{\min(n,m - 1)}C_{n}^{i}C_{m}^{i + 1}\)

總的複雜度爲 \(O(n^2logP)\) 不太行。

觀察這個式子。

\(\large\sum\limits_{i = 0}^{\min(n,m - 1)}C_{n}^{i}C_{m}^{i + 1} = \large\sum\limits_{i = 0}^{\min(n,m - 1)}C_{n}^{n - i}C_{m}^{i + 1} = \large C_{n+m}^{n+1}\)

中間那個式子和 \(C_{n}^{n}C_{m}^{1} + C_{n}^{n - 1}C_{m}^{2} + \dots + C_{n}^{n-\min(n,m-1)}C_{m}^{\min(n,m-1)+1}\) 等價,考慮一下他的實際意義其實就是把 \(n+m\) 個數分成左邊 \(n\) 個數,右邊 \(m\) 個數,從裏面選擇 \(n + 1\) 個數,是和 \(C_{n+m}^{n+1}\) 等價的。

總複雜度爲 \(O(nlogP)\)

Code

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define M 200002

typedef long long ll;
int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
inline void read(int &T) {
  int x = 0; bool f = 0; char c = getchar();
  while (c < '0' || c > '9') { if (c == '-') f = !f; c = getchar(); }
  while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
  T = f ? -x : x;
}

std::string s;
const int mod = 1e9 + 7;
int n, ans, jc[M], sum0[M], sum1[M];

int qpow(int a, int b) {
  int ans = 1, base = a;
  while (b) {
    if (b & 1) ans = 1ll * ans * 1ll * base % mod;
    base = 1ll * base * 1ll * base % mod;
    b >>= 1;
  }
  return ans % mod;
}

int main() {
  std::cin >> s; n = s.length(), jc[0] = 1, ans = 0;
  for (int i = 1; i <= n; ++i) jc[i] = 1ll * jc[i - 1] * 1ll * i % mod;
  for (int i = 0; i < n; ++i) {
    sum0[i + 1] = sum0[i];
    sum1[i + 1] = sum1[i];
    if (s[i] == '(') ++sum0[i + 1];
    else ++sum1[i + 1];
  }
  for (int i = 0; i < n; ++i) {
    if (s[i] == '(') {
      int res = 1ll * jc[sum0[i] + sum1[n] - sum1[i + 1]] * 1ll * qpow(1ll * jc[sum0[i] + 1] * 1ll * jc[sum1[n] - sum1[i + 1] - 1] % mod, mod - 2) % mod;
      ans = (1ll * ans + 1ll * res) % mod;
    }
  }
  std::cout << ans << '\n';
  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章