20171214,三四两题

3.凯南的括号

(matching.pas/c/cpp)

【问题描述】

   在学习括号匹配的时候,凯南在思考一个无聊的问题:能否找出双括号匹配的对数。

   具体问题是:给定长度为N(1 <= N <=50,000)的只包含左右(小)括号的字符串。能否找出相邻的两个左括号,和两个相邻的右括号,并且左括号的位置比右括号的位置靠左。

   当然这些两个左右括号很多,最终的问题是:能否找出有多少对不同的连续左右括号对。

   例如:给定括号序列  )((()())()),有四对不同的括号对匹配,具体如下,你不必考虑括号匹配的就近原则,只要考虑左括号在右括号左边即可。

1. )((()())())

 ^^   ^^

2. )((()())())

 ^^  ^^

3. )((()())())

    ^^     ^^

4. )((()())())

 ^^      ^^

【输入】

一个字符串,保证只包含左右小括号。字符创长度为N(1 <= N <= 50,000)

 

【输出】

一个整数,表示匹配的左右括号对。

 

【输入输出样例】

matching.in

matching.out

)((()())())

4


思路

1.读入数据(gets);2.统计每个双左括号的匹配右括号;3.累加输出。突然发现水的一逼…重点是如何统计匹配括号;其实双重循环就行,不过好像只能拿7、80。

 

4.小顾的字符游戏

(moo.pas/c/cpp)

【问题描述】

小顾和同学们喜欢玩一种游戏叫 "Moo".

他们总是站在一排,然后依次说出相应的一个字符,如果出错的同学,就要受到惩罚。

下面就是这个游戏的一个序列:

m o o m o o o m oo m o o o o m o o m o o o m o o m o o o o o

这个游戏的序列最初状态是 S(0) "m o o",也就是初始状态只有3个字符;如果要查询的字符超过3个,就要产生下一个字符序列,产生序列的规则如下:

s(k)是 s(k-1) +  "m o ... o"(k+2)个'o'  +s(k-1)

下面是相应的序列

S(0) = "m o o"

S(1) = "m o o m o o om o o"

S(2) = "m o o m o o om o o m o o o o m o o m o o o m o o"

注意:如果游戏的序列长度不够,就按照以上规则继续往下产生就可以了,所以游戏用的序列是无穷大的。

那么现在问题就出来了:

游戏中第x个人需要说的字符是什么呢?当然只有可能是 'm'或'o'.

本题有m(m<=10)个提问,每个提问给一个整数x,你要回答第x个人需要说出的字符数。

【输入】

第一行一个整数m(m<=10)

接下来m行,每行一个整数x (1 <=x<= 10^9)

 

【输出】

m行,每行一个字符,第i个人需要说的字符。

 

【输入输出样例1】

moo.in

moo.out

2

1

11

m

m

 

 题解:这道题体现有分治的思想把s[0]...s[n]看做是一层一层的话,那么s[0]有3个字符:3s[1]有10个字符:3+4+3=10s[2]有25个字符:3+4+3+5+3+4+3=10+5+10=25 ...所以可以把这每一层分成3个部分,判断出n在第几层第几部分后,进行递归,便可求出想要的字符下面的代码为了直观,直接将每层的数目求出放入数组了。

 代码如下:

#include<bits/stdc++.h>
using namespace std;
int m;
long long x,a[29]={0,3,10,25,56,119,246,501,1012,2035,4082,8177,16368,32751,65518,131053,262124,524267,1048554,2097129,4194280,8388583,16777190,33554405,67108836,134217699,268435426,536870881,1000000000};

void out(long long n,long long num)
{
    if(n==1)
        cout<<"m"<<endl;
    else 
        cout<<"o"<<endl;
}

void work(long long n)
{
    int num=0;
    if(n==1)
    {
        cout<<"m"<<endl;
        return;
    }
    else if(2<=n&&n<=3)
    {
        cout<<"o"<<endl;
        return;
    }
    for(int i=0;i<28;i++)
    {
        if(a[i]<n&&n<=a[i+1])
        {
            num=i;
            break;
        }
    }
    if(n<=a[num])
        out(n,a[num]);
    else if(a[num]<n&&n<=(a[num]+num+3))
    {
        n-=a[num];
        out(n,num+3);
    }
    else if((a[num]+num+3)<n&&n<=a[num+1])
    {
        if(a[num]<=num+3)
        {
            n-=a[num]+num+3;
            out(n,a[num]);
        }
        else
        {
            n-=a[num]+num+3;
            work(n);
        }
    }
    
}

int main()
{
    freopen("moo.in","r",stdin);
    freopen("moo.out","w",stdout);
    cin>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>x;
        work(x);
    }
    return 0;
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值