链接:https://ac.nowcoder.com/acm/contest/9981/B
来源:牛客网
题目描述
请你构造一个非空的括号字符串,包含正好 kkk 个不同合法括号对。
所谓括号字符串,是指由'('和')'这两种字符构成的字符串。
要求构造的字符串长度不超过100000 100000100000。
输入描述:
一个整数 kkk。
0≤k≤1090leq k leq 10^90≤k≤109
输出描述:
一个仅包含左右括号字符串,其中有 kkk 个合法的括号对。如果有多种构造方法,输出任意一种合法方案即可。
示例1
输入
3
输出
()()
说明
假设字符串数组下标从 1 开始,则 (1,2), (1,4), (3,4) 共计 3 个合法括号对
当然,"()))" 也是一种合法的构造
示例2
输入
4
输出
(())
说明
假设字符串数组下标从 1 开始,则 (1,3), (1,4), (2,3), (2,4) 共计 4 个合法括号对
另外,合法的构造还有"())()"、"()(()(" 等等。。
示例3
输入
9
输出
()))))))))
说明
合法的还可以是:
())())()
((()))
)()()())(
等等等。。有非常多种合法构造,输出任意即可。
最开始是想按照(())))()类型来写的,也就是大概是一半的长度,不过俺写的没过,后来看讲解发现竟然需要考虑0,不过修改了还是没能过,所以还需要继续修改。
于是修改思路,(((())))像这一种,得到的个数是k^2,所以能够最大限度的缩短字符长度。此外还是需要考虑0这种情况。比如现在有一个长度为115,那么理论上应该是在100( (((((((((()))))))))) k = 10 )的基础上进行操作。在右边加上一个右括号就是加上了十个括号,所以考虑提取剩下括号数中k的倍数,right = 1,只需要在右边多加一个右括号。此时还剩下五个括号,只能考虑在右括号中插入一个左括号,使右边增加五个括号(left = 5),于是最后得到:
#include <iostream> #include <cstdio> #include <cmath> #include <string> using namespace std; int main() { int n; cin>>n; string s = ""; if(n == 0) s += '('; else { int k = sqrt(n); for(int i = 0;i < k;i++) // 利用()类型,已有 k*k 个括号 s += '('; // 暂时只打印 ( ,因为可能在 ) 中还需要加入 ( // 已有 k*k 个括号 int right = (n - k * k) / k; // 计算还需要几个 ) int left = n - k * k - right * k; // 计算需要插入 ( 的位置 int sign = 0; // 标记是否需要插入 ( ,判断left是否为零 if(left) sign = 1; for(int i = k + right + sign;i > 0 ;i--) if(sign && i == left + 1) // 打印 ) ,同时打印需要的 ( s += '('; else s += ')'; } /* 71 k = 8 right = 0 left = 7 (((((((()())))))) */ cout<<s<<endl; return 0; }
2021-02-02