合法的括号序列: )出现在( 前面 一定是不合法的,然后要保证左右括号一样多
才是一个合法的括号序列
题目1
长度为20的合法括号序列有多少个?
将这些合法括号序列按照字典序排序,第1个括号序列是”(((((((((())))))))))”,求第2022个括号序列
第一行输出一个数字,表示第一问的答案。
第二行输出一个长度为20的合法括号字符串,仅包含”(“和”)”,表示第二问的答案。
因为括号序列只包括(和)联想到二进制 也只包含0或1 两种,所以可以用二进制枚举所有序列
然后判断是否是合法括号序列,0或1 哪个代表(或者)都是一样的都会枚举到
#include <bits/stdc++.h>
using namespace std;
string c;
bool ok;
int Left, k, ans;
string a[100010];
int main()
{
for (int i = 0; i < 1 << 20; i++)
{
c = "";
ok = true;
Left = 0;
for (int j = 0; j < 20; j++)
{
if (i >> j & 1)
Left++, c += '(';
else
Left--, c += ')';
if (Left < 0)
ok = false;
}
if (Left > 0)
ok = false;
if (ok)
ans++, a[k++] = c;
}
sort(a, a + k);
cout << ans << '\n';
cout << a[2021] << '\n';
return 0;
}
题目2
https://ac.nowcoder.com/acm/contest/11222/D
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
string c;
int num;
ll qmi(ll a, ll b, ll p)
{
ll res = 1;
while (b)
{
if (b & 1)
res = res * a % p;
b >>= 1;
a = a * a % p;
}
return res;
}
int main()
{
cin >> c;
int n = c.size();
int Left = 0;
bool ok = true;
for (int i = 0; i < n; i++)
{
if (c[i] == '(')
Left++;
else
Left--;
if (Left < 0) //任意位置右括号多,一定是不合法的
ok = false;
if (Left == 0) //统计包含多少个合法的括号
num++;
}
if (Left > 0) // 左右括号数量不同
ok = false;
// num个合法括号,中间有num-1个空,每个空可以选择切与不切
if (ok)
{
cout << qmi(2, num - 1, mod) << '\n';
}
else
cout << -1 << '\n';
return 0;
}