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;
}