CF785D Anton and School - 2
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF785D Anton and School - 2相关的知识,希望对你有一定的参考价值。
题意:
给定一个长度≤2×10^5由(和)组成的字符串,问有多少个子串(可以不连续),前半部分是由(组成后半部分由)组成.
题解:
怎么括号匹配能出这么多题
如何才能不重不漏的选出所有括号呢?
枚举每个位置的i时,我们通过i左括号数量和右括号的数量,可以算出当i为最后一个左括号时满足条件的子序列数量。这样统计括号数量不会重,不会漏。(第i位是右括号的情况都会被包含其中,不会漏)
我们设左边有a个左括号(包括自己),右边有b个右括号,满足条件的字串有:
C
a
−
1
0
C
b
1
+
C
a
−
1
1
C
b
2
+
.
.
.
+
C
a
−
1
x
C
b
x
+
1
+
.
.
.
=
∑
i
=
0
m
i
n
(
a
−
1
,
b
−
1
)
C
a
−
1
x
C
b
x
+
1
C_{a-1}^{0}C_{b}^{1}+C_{a-1}^{1}C_{b}^{2}+...+C_{a-1}^{x}C_{b}^{x+1}+...=\\sum_{i=0}^{min(a-1,b-1)}C_{a-1}^{x}C_{b}^{x+1}
Ca−10Cb1+Ca−11Cb2+...+Ca−1xCbx+1+...=i=0∑min(a−1,b−1)Ca−1xCbx+1
从左侧a-1个左括号中选x个,还有第i位本身这个左括号,再从右侧b个右括号中选x+1个,组成一个合法的括号序列
然后怎么做?
暑假多校的时候学到一个东西:范德蒙德卷积,我经常当做组合数的定理来记。
∑
i
=
0
k
C
n
i
C
m
k
−
i
=
C
n
+
m
k
\\sum_{i=0}^{k}C_{n}^{i}C_{m}^{k-i}=C_{n+m}^{k}
i=0∑kCniCmk−i=Cn+mk
严谨的证明,可以用二项式定理证得,具体证明我也不知道,不过其中的含义挺好理解,在n物品中取i个,m个物品中k-i个,就是在n+m个物品中取k个
回到本题上:
我们现在有
∑
i
=
0
m
i
n
(
a
−
1
,
b
−
1
)
C
a
−
1
x
C
b
x
+
1
=
∑
i
=
0
m
i
n
(
a
−
1
,
b
−
1
)
C
a
−
1
a
−
1
−
x
C
b
x
+
1
=
C
a
+
b
−
1
a
\\sum_{i=0}^{min(a-1,b-1)}C_{a-1}^{x}C_{b}^{x+1}=\\sum_{i=0}^{min(a-1,b-1)}C_{a-1}^{a-1-x}C_{b}^{x+1}=C_{a+b-1}^{a}
∑i=0min(a−1,b−1)Ca−1xCbx+1=∑i=0min(a−1,b−1)Ca−1a−1−xCbx+1=Ca+b−1a
这一下子不久好做多了,然后从第一位开始枚举,如果是左括号就计算这个组合数,记录答案
代码:
#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{
x= 0;
char c= getchar();
bool flag= 0;
while (c < '0' || c > '9')
flag|= (c == '-'), c= getchar();
while (c >= '0' && c <= '9')
x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();
if (flag)
x= -x;
read(Ar...);
}
template <typename T> inline void write(T x)
{
if (x < 0) {
x= ~(x - 1);
putchar('-');
}
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#else
startTime= clock();
freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#else
endTime= clock();
printf("\\nRun Time:%lfs\\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn= 2e5 + 9;
const int mod= 1e9 + 7;
ll poww(ll a, ll b)
{
ll ans= 1;
while (b) {
if (b & 1)
ans= ans * a % mod;
a= a * a % mod;
b>>= 1;
}
return ans % mod;
}
ll fac[maxn], inv[maxn];
void init(int N)
{
fac[1]= 1;
for (int i= 2; i <= N; i++) {
fac[i]= (fac[i - 1] * i) % mod;
}
inv[N]= poww(fac[N], mod - 2) % mod;
// cout << inv[N] << endl;
for (int i= N - 1; i >= 0; i--) {
inv[i]= inv[i + 1] * (i + 1) % mod;
}
}
int R[maxn];
ll C(ll a, ll b)
{
if (a < b || a < 0 || b < 0)
return 0;
// cout << "=" << (fac[a] % mod * (inv[b] %'' mod)) % mod * (inv[a - b] % mod) % mod << endl;
return (fac[a] % mod * (inv[b] % mod)) % mod * (inv[a - b] % mod) % mod;
}
int main()
{
//rd_test();
init(200000);
string s;
cin >> s;
int len= s.length();
for (int i= len - 1; i >= 0; i--) {
R[i]= R[i + 1] + ((s[i] == ')') ? 1 : 0);
// cout << R[i] << endl;
}
int sum= 0;
int tot= 0;
for (int i= 0; i < s.length(); i++) {
if (s[i] == '(') {
tot++;
sum= (sum + C(tot + R[i] - 1, R[i] - 1) + mod) % mod;
}
}
cout << sum;
//Time_test();
}
以上是关于CF785D Anton and School - 2的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces 785D Anton and School - 2
codeforces 785D D. Anton and School - 2