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语言学的渣的一笔..靠考前突击才基本掌握了语法 寒假突然醒悟, ...
随机推荐
- 机器学习实战之k-近邻算法(3)---如何可视化数据
关于可视化: <机器学习实战>书中的一个小错误,P22的datingTestSet.txt这个文件,根据网上的源代码,应该选择datingTestSet2.txt这个文件.主要的区别是最后 ...
- JasperReports报表表达式12
报表表达式是JasperReports使我们能够显示在报表上的数据计算的强大功能.计算出数据不是一个静态数据,并且不受特别的报表参数或数据源字段传递的数据.报表表达式是由组合报表参数,字段和静态数据. ...
- TZOJ 2965 A Coin Game(DP)
描述 Farmer John's cows like to play coin games so FJ has invented with a new two-player coin game cal ...
- Leetcode476.Number Complement数字的补数
给定一个正整数,输出它的补数.补数是对该数的二进制表示取反. 注意: 给定的整数保证在32位带符号整数的范围内. 你可以假定二进制数不包含前导零位. 示例 1: 输入: 5 输出: 2 解释: 5的二 ...
- VS2013生成、使用dll,lib文件
VS2013生成DLL文件 vs2013创建及使用DLL 一般来说项目偏爱生成dll动态库文件,因为可以解决静态库造成的空间浪费和更新困难问题,另外创建静态库时,我一般是建立空项目后,在项目配置类型中 ...
- 【python之路32】python异常处理
一.捕获异常 1.try except #!usr/bin/env python # -*- coding:utf-8 -*- num = input("请输入一个数字:") t ...
- js 实现继承
我们现在要做的一件事情是像其他语言的面向对象一下实现继承多态 具体要求如下: 一个 Father 构造函数,一个 Child 构造函数,其中改写 Father中的部分参数, new Child() 表 ...
- jquery 获取图片宽高为0的问题
原理:页面加载完了,图片不一定加载完了. $(function(){ $("img").on("load",function(){ //核心 var w = $ ...
- TomCat 启动默认加载项目
在最后加上这句代码即可:<Context path="" docBase="\项目名称" reloadable="true" cros ...
- MySQL--视图、触发器、事务、存储过程、内置函数、流程控制、索引
视图 触发器 事务 存储过程 内置函数 流程控制 索引 视图 1.什么是视图 视图就是通过查询得到一张虚拟表,然后保存下来,下次直接使用即可 2.为什么要用视图 如果要频繁使用一张虚拟表,可以不用重复 ...