dfs暴力模拟 Moo(洛谷 P1885)

本文探讨了一个有趣的字符串生成问题,奶牛Bessie遵循特定规则构造字符串,直至达到指定长度N。问题在于确定第N个字符是‘m’还是‘o’。通过递归生成和优化算法,我们提供了两种解法,一种直接构造字符串,另一种通过模拟避免了空间溢出。
摘要由CSDN通过智能技术生成

Moo

题目描述

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

S(0) = “moo”

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

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

………

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

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

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

输入格式

一个整数N。

输出格式

一个字符,m或者o

输入 #1

11

输出 #1

m

第 i 个字符串的长度为 a[i]=2*a[i-1]+i+3; 先预处理出长度为 n 的字符串是第几个字符串;也就是说要连接几次;

解法一:
根据要连接几次,然后把字符串连接起来,求n的位置的字符;

但是只有80分,因为n的范围为1e9;爆了空间;

#include<bits/stdc++.h>
using namespace std;
int n;
int a[100000];
string dfs(int p){
	string s="";
	if(p==0){
		return "moo";
	}
	string ss="";
	for(int i=1;i<=p+2;i++) ss+="o";
	string b=dfs(p-1);
	return b+"m"+ss+b;
}
int main(){
	scanf("%d",&n);
	a[0]=3;
	int ans;
	for(int i=1;;i++){
		a[i]=2*a[i-1]+i+3;
		if(a[i]>=n){
			ans=i;
			break;
		}
	}
	string s=dfs(ans);
	cout<<s[n-1]<<endl;
	return 0;
}

解法二:

看代码模拟一下,应该就可以了吧;

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
#define N 500100
#define M 2000010
using namespace std;
int n;
int a[100000];
void dfs(int p,int q){//p为剩余的长度,q为第几个字符串 
	while(a[q-1]>p) q--;
	if(p==a[q-1]+1){
		cout<<"m"<<endl;
		return;
	} 
	else if(p<=a[q-1]+q+3){
		cout<<"o"<<endl;
		return;
	}
	dfs(p-a[q-1]-q-3,q-1);
}
int main(){
	scanf("%d",&n);
	a[0]=3;
	int ans;
	for(int i=1;;i++){
		a[i]=2*a[i-1]+i+3;
		if(a[i]>=n){
			ans=i;
			break;
		}
	}
	dfs(n,ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值