P1885 Moo

P1885 Moo

题目描述
奶牛 Bessie 最近在学习字符串操作,它用如下的规则逐一的构造出新的字符串:

S(0) =S(0)= moo

S(1) = S(0) +S(1)=S(0)+ m + ooo + S(0) =+S(0)= moo + m + ooo + moo = moomooomoo

S(2) = S(1) +S(2)=S(1)+ m + oooo + S(1) =+S(1)= moomooomoo + m + oooo + moomooomoo = moomooomoomoooomoomooomoo

Bessie 就这样产生字符串,直到最后产生的那个字符串长度不小于读入的整数 NN 才停止。

通过上面观察,可以发现第 kk 个字符串是由:第 k-1k−1 个字符串 + m + (k+2(k+2 个 o) +o)+ 第 k-1k−1 个字符串连接起来的。

现在的问题是:给出一个整数 N(1≤N≤10 9 ),问第 NN 个字符是字母 m 还是 o?

输入格式
一个正整数 NN。

输出格式
一个字符,m 或者 o。

输入输出样例
输入
11
输出
m
说明/提示
样例解释:

由题目所知:字符串S(0) 是 moo, 现在要求第 11 个字符,显然字符串 S(0) 不够长;

同样 S(1)的长度是 10,也不够长;S(2) 的长度是25,够长了,S(2) 的第 11 个字符是 m,所以答案就输出 m。

思路
分治, 首先预处理一下第n个字符在被包含在第几个字符串里.然后在把这个字符串分成1,2,3三个区间(1区间和3区间是一模一样的字符),然后判断n在第几个区间,不断分治,将大问题分成几个小问题去求解,最后注意边界处理即递推到了第一个字符串.

#include<bits/stdc++.h>
using namespace std;

int a[100005],t;//t表示输入的那个字符在第几层
//a[i]表示第i层字符串的长度,比如a[0]=3,表示字符串“moo”

int cur(int x){//用来求出第x个字符在第几层,并且顺便保存了从a[0]开始的每一层有多少字符
	int sum=3;//第0层
	int k=1;
	while(sum<x){//直到求出大于要求的字符长度的那个数组长度
		sum=sum*2+1+k+2;
		a[k]=sum;//第k层字符串有多少个
		k++;
	}
	return k-1;//它的上一层即为所求
}

char check(int n,int t){//第n个字符,起初在第t层
	if(t==0){
		if(n==1) return 'm';
		if(n==2||n==3) return 'o';
	}
	
	if(n<=a[t-1]) return check(n,t-1);如果在第1区间
	if(n>a[t]-a[t-1]) return check(n-(a[t]-a[t-1]),t-1);//如果在第3间
	if(n==a[t-1]+1) return 'm';//如果在第2区间
	return 'o';//因为第2个区间时候1个'm'和k个'o'组成,所以n如果是第2区间的第一个数,则返回'm',否则返回'o'
}

int main(){
	int n;cin>>n;
	a[0]=3;
	t=cur(n);//求出第n个字符在第几层
	char ch=check(n,t);
	cout<<ch; 	
	return 0;
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛小y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值