2017校赛 问题 D: 我知道了,你知道了吗?【递归】
题目描述
Alice和Bob走在去学校的路上,听到两个路人的对话:
路人甲:我知道了, 你知道了吗?
路人乙:我知道你知道了,你知道了吗?
路人甲:我知道你知道我知道了,你知道了吗?
路人乙:我知道你知道我知道你知道了,你知道了吗?
.........
他们便觉得十分有趣,觉得非常像两个人在玩字符串拼接的游戏,受此启发,Alice和Bob玩起了”类似”的拼接游戏:
Alice首先会选择四个字符串S1, A, B, C,之后Alice和Bob轮流拼接出第2,第3,第4....第n个字符串,对于第i个字符串Si (i > 1), 它的拼接规则是Si = A + Si-1 + B + Si-1 + C,其中符号“+”是字符串连接的意思,举个例子:
Alice先选择了S1 = “ab”, A = “CD”, B = “EF”, C = “GH”,接下来的操作是:
Bob 拼接出 S2 = “CDabEFabGH”
Alice拼接出 S3 = “CDCDabEFabGHEFCDabEFabGHGH”
...........
走在路上的你恰巧看到了Alice和Bob玩游戏的整个过程,Alice就问你,在他们拼出的第n个字符串中的第k个字符是什么?Alice和Bob都已经知道了,你知道了吗?假设无论多长的字符串Alice和Bob都能拼接出来。
注意引号是定界符,不属于字符串。
输入
输入包括多组数据(数据组数总共不超过50)。
每组第一行有四个字符串,分别是S1, A, B, C(长度都<=100),字符串只包含小写英文字母和大写英文字母.
第二行一个整数q(1 <= q <= 50),表示Alice询问的次数。
接下来有q行, 每组两个整数n(1 <= n <= 1000)和k(1 <= k <= 100000000),分别代表Alice和Bob拼接出的第n个字符串以及第n个字符串中的第k个字符。
输出
对于每个n和k,输出对应的Alice和Bob拼接出的第n个字符串中第k个字符。如果第n个字符串中第k个字符不存在输出’*’。每个答案独占一行。
样例输入
ab CD EF GH
5
1 1
1 2
1 3
2 10
2 11
样例输出
a
b
*
H
* 越补题越崩溃,点背加经验少。。。。
记录下个人思路:
显然第n个字符串是个递推式:
那么我求第n个字符串的第k个字符只需要判断k的范围即可,如果k<=len(A),就在A中找相应位置,如果k>len(A)&&k<=len(Sn-1)就递归到Sn-1,在Sn-1中找第k-len(A)个位置,以此类推。。。。
所以这道题刚开始我这样写:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int ls,la,lb,lc;
int s[];
char s1[],A[],B[],C[]; void solve(int n,int k)
{
if(n==){
printf("%c\n",s1[k-]);
return;
}
if(k<=la){
printf("%c\n",A[k-]);
return;
}else if(k>la+s[n-]&&k<=la+s[n-]+lb){
printf("%c\n",B[k-la-s[n-]-]);
return;
}else if(k>la+lb+*s[n-]&&k<=la+lb+lc+*s[n-]){
printf("%c\n",C[k-la-lb-*s[n-]-]);
return;
}else if(k>la&&k<=la+s[n-]){
solve(n-,k-la);
return;
}else {
solve(n-,k-la-lb-s[n-]);
return;
}
} int main()
{
while(scanf("%s%s%s%s",s1,A,B,C)==)
{
memset(s,,sizeof(s));
ls=strlen(s1);la=strlen(A);
lb=strlen(B);lc=strlen(C);
s[]=ls;
for(int i=;i<=;i++){
s[i]=s[i-]*+la+lb+lc;
}
int q,n,k;
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&n,&k);
if(k>s[n]) printf("*\n");
else{
solve(n,k);
}
}
}
return ;
}
错误写法
显然,运行错误(段错误),就是超数组边界了。后来再想想,len(Sn)=2*len(Sn-1)+len(A)+len(B)+len(C)==>len(Sn)=2^(n-1)len(s1)+(4*n-5)*[len(A)+len(B)+len(C)](大概推了一下,可能有错误)。可以看出,字符串的长度是呈指数形式增长的,自然存到n=30数就已经很大很大了,又有k<=10^8,那么也就是说即便S1,A,B,C长度均为1,n==28时已经大于这个数了(2^27约为134217728)。所以当n>=28时长度已经足够达到k的最大值。所以我只存到n=28,当n>28时根据递推式推到n<=28的范围内再用上面的做法解决。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
ll ls,la,lb,lc;
ll s[];
char s1[],A[],B[],C[]; void solve(int n,int k)
{
if(n==){
printf("%c\n",s1[k-]);
return;
}
if(k<=la){
printf("%c\n",A[k-]);
return;
}else if(k>la+s[n-]&&k<=la+s[n-]+lb){
printf("%c\n",B[k-la-s[n-]-]);
return;
}else if(k>la+lb+*s[n-]&&k<=la+lb+lc+*s[n-]){
printf("%c\n",C[k-la-lb-*s[n-]-]);
return;
}else if(k>la&&k<=la+s[n-]){
solve(n-,k-la);
return;
}else {
solve(n-,k-la-lb-s[n-]);
return;
}
} int main()
{
while(scanf("%s%s%s%s",s1,A,B,C)==)
{
memset(s,,sizeof(s));
ls=strlen(s1);la=strlen(A);
lb=strlen(B);lc=strlen(C);
s[]=ls;
for(int i=;i<=;i++){
s[i]=s[i-]*+la+lb+lc;
}
int q,n,k;
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&n,&k);
int pos=;
for(int i=;i<=;i++)
if(s[i]>=k){
pos=i;break;
}
if(pos>n) printf("*\n");
else if(n<=){
solve(n,k);
}else {
int t=la*(n-);
if(t>=k){
int r=k%la;
printf("%c\n",A[r]);
}else{
solve(,k-t);
}
}
}
}
return ;
}
2017校赛 问题 D: 我知道了,你知道了吗?【递归】的更多相关文章
- 2017校赛 问题 F: 懒人得多动脑
题目描述 小D的家A和学校B都恰好在以点F为焦点的双曲线上,而小D每日所需的生活水源在一条平行该双曲线准线的直线上,设它的值为v.大家都知道,每天都是要喝水的,但是小D有点懒,他希望自己能在去上学或者 ...
- 北工大2017校赛 1101:要打车的FanZzz
题目链接: http://bjutacm.openjudge.cn/lianxi/1101/ 思路: 二分 + 二分图最大匹配. 开始的时候我想直接用最小费用流模型,后来发现这样是错误的.因为这道题实 ...
- 广工2017校赛-F-- tmk找三角
http://gdutcode.sinaapp.com/problem.php?cid=1056&pid=5 Description 有一棵树,树上有只tmk.他在这棵树上生活了很久,对他的构 ...
- 2017 校赛 问题 B: CZJ-Superman
题目描述 “那是只鸟?那是飞机?那是——超人!” 程序员在看完<CZJ-Superman>之后,励志要成为一名“CZJ-Superman”,学会了两个特殊技能ZZZ和JJJ,足以成为一名“ ...
- 2017 校赛 问题 E: 神奇的序列
题目描述 Aurora在南宁发现了一个神奇的序列,即对于该序列的任意相邻两数之和都不是三的倍数.现在给你一个长度为n的整数序列,让你判断是否能够通过重新排列序列里的数字使得该序列变成一个 ...
- 2017校赛 C: 不爱学习的小W【模拟】
题目描述 “叮铃铃”上课了,同学们都及时到了教室坐到了座位上,教室里有n行m列的座位而且刚好坐满.既然是上课,那老师叫学生回答问题就是再正常不过的事了,同样地,教室里也就有爱学习和不爱学习的学生了,爱 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- SCNU省选校赛第二场B题题解
今晚的校赛又告一段落啦,终于"开斋"了! AC了两题,还算是满意的,英语还是硬伤. 来看题目吧! B. Array time limit per test 2 seconds me ...
- 2014上半年acm总结(1)(入门+校赛)
大一下学期才开始了acm,不得不说有一点迟,但是acm确实使我的生活充实了很多,,不至于像以前一样经常没事干= = 上学期的颓废使我的c语言学的渣的一笔..靠考前突击才基本掌握了语法 寒假突然醒悟, ...
随机推荐
- Redis学习笔记02-消息队列与延时队列
写在前面:Redis的消息队列并不是专业的消息队列,没有ACK保证,没有特别多的高级特性,如果对消息的可靠性有很高的要求,就放弃它吧. 1.Redis消息队列 Redis通过内部的list数据结构来实 ...
- 应读的paper
1.Faster R-CNN:https://arxiv.org/abs/1506.01497(已读) 2.FPN(Feature Pyramid Networks for Object Detect ...
- javascript基础:dom
Dom: * 概念:Document Object Model 文档对象模型 * 将标记语言文档的各个组成部分,封装成对象,可以使用这些对象,对标记语言文档进行CRUD的动态操作 * D ...
- Docker(四)安装Redis
1.安装redis https://blog.csdn.net/qq_29917523/article/details/78019511 2.测试连接
- vue项目中实现扫码功能
项目地址:https://github.com/wkl007/vue-scan-demo.git 项目主要是做的一个扫码的功能 核心代码为 <div class="scan" ...
- AppServer初始化渠道
1.写了一个拦截器(RequestInterceptor) 2.里边有个有一个doRequest()方法 3.初始化渠道的方法(initRequestContext()) -------------- ...
- JavaScript内容梳理 示例之模态对话框 示例之全选和反选以及取消 示例之后台管理左侧菜单
<!DOCTYPE html> <!--示例之模态对话框--> <html lang="en"> <head> <meta c ...
- TZ_10_spring-AOP日志处理
1.在某个用户登陆后台后对其每一项操作进行保存日志处理 LogAopController @Component @Aspect public class LogAop { @Autowired pri ...
- canvas扇形进度圈动态加载
效果图如下:动态加载的 实现代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta cha ...
- 前端(jQuery)(5)-- jQuery AJAX异步访问和加载片段
异步访问 index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset ...