D. Guess The String

传送门
https://codeforces.com/contest/1697/problem/D

题意

给定一个长为n的字符串(n<=1000),你可以用最多26次操作一和最多6000次操作二来猜出这个字符串。

有两种操作:

操作一:选择一个位置p,得到第p个字符。

操作二:选择一段区间l,r,得到[l,r]这段区间有多少不同的字母。

分析:看到26和6000,容易想到log(26)=6,考虑二分。假设当前位置在i,且i之前的字母全部确定,容易想到二分m,每次查看操作二[m,i]和[m,i-1]的答案是否相同来确定当前字母,如果这个字母没有在之前出现过,那么用操作一。至此,需要用操作二n*2*log(n)次,我们需要一些优化。发现二分到最后确定的字母一定是这个字母最后一次出现,所以我们记一个pos数组,用于记录每个字母最后一次出现的位置,每次二分也只二分这些位置,需要的操作二次数来到n*2*6次。这时候其实已经不用两次使用操作二了,直接二分m是前面出现的第几个字母即可,至此,需要的操作二次数来到n*6次。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
char ans[1005];
int pos[30];//记录每个字母最后出现的位置
int cnt;

char ask1(int p)
{
	cout<<"? 1 "<<p<<endl;
	char c;
	cin>>c;
	return c;
}

int ask2(int l,int r)
{
	cout<<"? 2 "<<l<<" "<<r<<endl;
	int x;
	cin>>x;
	return x;
}

signed main()
{
	int n;
	cin>>n;
	ans[1]=ask1(1);
	pos[++cnt]=1;
	for(int i=2;i<=n;i++)
	{
		sort(pos+1,pos+cnt+1);
		int l=1,r=cnt,p=-1;
		while(l<=r)//查找当前ans[i]在前面出现的位置p
		{
			int m=l+r>>1;
			if(ask2(pos[m],i)==cnt-m+1)
			{
				l=m+1;
				p=m;
			}
			else r=m-1;
		}
		if(p==-1)
		{
			char c=ask1(i);
			ans[i]=c;
			pos[++cnt]=i;
		}
		else
		{
			ans[i]=ans[pos[p]];
			pos[p]=i;
		}
	}
	cout<<"! ";
	for(int i=1;i<=n;i++)
	{
		cout<<ans[i];
	}
	cout<<endl;
}

好的,以下是一个简单的猜字谜游戏的Go语言代码示例: ```go package main import ( "fmt" "math/rand" "time" ) var words = []string{"apple", "banana", "cherry", "orange", "peach"} func main() { rand.Seed(time.Now().UnixNano()) word := words[rand.Intn(len(words))] fmt.Println("Guess the word!") fmt.Println("The word has", len(word), "letters") fmt.Println("Enter a letter or the full word:") guesses := make([]string, 0) maxGuesses := 10 for remainingGuesses := maxGuesses; remainingGuesses > 0; remainingGuesses-- { fmt.Printf("%d guesses remaining: ", remainingGuesses) var guess string fmt.Scanln(&guess) if guess == word { fmt.Println("Congratulations, you guessed the word!") return } else if len(guess) != 1 { fmt.Println("Please enter a single letter or the full word") continue } if contains(guesses, guess) { fmt.Println("You already guessed that letter") continue } guesses = append(guesses, guess) if contains(word, guess) { fmt.Println("Correct!") } else { fmt.Println("Incorrect!") } } fmt.Println("Sorry, you ran out of guesses. The word was", word) } func contains(str string, substr string) bool { return len(substr) == 1 && rune(substr[0]) == []rune(str)[0] } func containsSlice(slice []string, str string) bool { for _, s := range slice { if s == str { return true } } return false } ``` 这个代码首先定义了一个字谜单词列表,然后随机选择一个单词。游戏开始时,程序给出一些提示,并且允许玩家猜测字母或完整单词。玩家有一定的猜测次数,如果在次数内猜到了单词,则游戏胜利,否则游戏失败。 在游戏过程中,程序会记录玩家的猜测并给出相应的反馈。如果玩家已经猜过某个字母,则程序会提示玩家不要再次猜测。如果猜测的字母在单词中出现,则程序会告诉玩家猜测正确,否则提示猜测错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chmpy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值