2021牛客寒假算法基础集训营1-B题

博客详细介绍了如何解决2021牛客寒假算法基础集训营1-B题,通过数学和逻辑分析构造括号字符串。首先确定匹配括号对数,然后输出算术平方根个左括号,再根据余数插入剩余括号,确保正确匹配。文中还特别处理了k小于等于3的特殊情况,并解释了代码中i++的必要性。
摘要由CSDN通过智能技术生成

2021牛客寒假算法基础集训营1-B题

先直接上代码吧。

#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
#define ll long long
int main()
{
    int k;
    //freopen("W:\\Programing\\testinput.txt","r",stdin);
    //freopen("W:\\Programing\\outandin.txt","w",stdout);
    while(scanf("%d",&k)!=EOF)
    {
        //printf("%d  ",k);
        if (k<=3)
        {
            if (k==0) printf("(\n");
            if (k==1) printf("()\n");
            if (k==2) printf("(()\n");
            if (k==3) printf("()()\n");
            continue;
        }
        int step=sqrt(k);
        //printf("sqrt==%d  ",step);
        int reminder=(k-step*step);//reminder表示余数
        int ans=reminder%2;//判断还需要偶数对还是奇数对括号;

        for(int i=1;i<=step;i++)    printf("(");//首先输出sqrt(k)个左括号;

        int cnt=step+reminder/2+reminder%2;
        for(int i=cnt;i>=1;i--)
        {

            if(i==2+ans+reminder/2)    //输出reminder/2个(
            {
                for(int j=1;j<=reminder/2;j++,i--)
                    printf("(");
                i++;//自己可以调试一下,看为什么要多这一步
            }
            else if (ans==1&&i==2)     printf("(");
            else printf(")");

        }
        printf("\n");
    }
    return 0;
}

个人思路:

首先我们知道,每个左括号都可以和它右边的右括号成功匹配;我们先反过来想,对于一个括号字符串(仅包含()的字符串)这个字符串所包含的匹配括号对数就可以很容易求出来:

匹配的括号对数=所有的(左括号 *它右边右括号的括号数量)的和;

那么 我们就先输出k的算术平方根个( ;接下来就是除了输出k的算术平方根个)还有就是如何把k-(int)sqrt(K)*(int)sqrt(K)对括号输出,我个人采用的方法是,首先,int cnt=step+reminder/2+reminder%2;cnt表示还需要多少个括号,通过reminder/2(整除!!!)计算出来在如果我用构造的括号字符串的最后两个)和前面(匹配的话,需要多少个( 。这里解释一下,为什么是最后两个)?而不是三个、四个呢?因为如果用最后两个的话,要么可以在第sqrt(k)(括号后面添加reminder/2(完全匹配,要么会少一对括号不能达到k个括号,那么剩下的一对括号就可以通过在最后一个)的前面添加一个( 实现。

下面举一个例子可能会更加清楚:
15==3*3+3*2;
我们可以先构造九对匹配的括号((()));就这样,然后我们再把三个(插入到合适的位置,
倒数2+reminder%2+reminder/2个位置开始输出(,而且15-3*3==6 为偶数,所以最终构造为
((()((()).

第二个例子:
19==4*4+1*2+1
同理:先构造(((())))已经把平方数的构造出来了,接着我们需要把1个(插入到倒数2+reminder%2+reminder/2个位置,这样操作之后,还剩下一对括号,那么再倒数第一个)前面插入一个(就完成了我们的构造。

具体的构造步骤可以自己输入几个数据,小一点吧,太大了也不好,不容易看出来;

还有最后一个问题就是代码里面的i++的问题了,简单说一下吧;当里里面的for循环执行完毕的时候,已经对i进行了递减操作,但是外面的for循环会再次执行一遍i–,这样,i就多减了一次,所以必须要i++;可以自己打个断点,观察一下哟;

还有就是,我的代码里面的` if (k<=3)

 if (k<=3)
 {
       if (k==0) printf("(\n");
       if (k==1) printf("()\n");
       if (k==2) printf("(()\n");
       if (k==3) printf("()()\n");
       continue;
 }

首先是要对k=0进行特判,因为题目要求非空,其次就是,当k=3的时候按照下面的代码输出的结果是不对的,k=2和k=3的输出结果是一样的,这个情况比较特殊,最直接的办法就是把k=3也给特判了。虽然这一题没有k=3这个数据(试过了,只特判0也可以过)。但还是加上吧,毕竟追求严谨还是好的;

如有错误,欢迎指正哟

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值