B--括号

链接:https://ac.nowcoder.com/acm/contest/9981/B
来源:牛客网

题目描述

请你构造一个非空的括号字符串,包含正好 kkk 个不同合法括号对。
所谓括号字符串,是指由'('和')'这两种字符构成的字符串。
要求构造的字符串长度不超过100000 100000100000。

输入描述:

一个整数 kkk。
0≤k≤1090leq k leq 10^90k109

输出描述:

一个仅包含左右括号字符串,其中有 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

原文地址:https://www.cnblogs.com/2015-16/p/14362807.html