外星猫和朝三暮四题解

本文探讨了两道有趣的编程题——'外星猫'和'朝三暮四'。对于'外星猫'问题,通过分析得出递推公式a[i]=a[i-1]*2+i-1,解决了基因变化的查询。对于'朝三暮四',利用状态转移方程dp[i][j][k]=dp[i-1][j-k][0]+...+dp[i-1][j-k][k],求解猴子分栗子的方案数。提供了解题思路及具体代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

外星猫:(一只猫,原来的基因是“cat”,第二秒变成“catacat”,第三秒变成“catacataacatacat”,以此类推,询问猫的第i个基因是什么,什么时候出现的)

首先,这道题不可能模拟猫的基因(模拟一定会超时),我们可以开一个数组a[i]表示第i秒钟猫的基因长度,而且根据题目可以得到一个递推式:a[i]=a[i-1]*2+i-1。这样就可以直接解决第二个问题。对于第一个问题,我们可以把a[q](假设a[q]时猫的基因长度正好大于要求的i)长度的基因分成三部分——第一部分:第q-1秒时猫的基因;第二部分:第q秒时猫基因内添加的那一段a;第三部分:第q秒复制第q-1秒时的那一段基因——然后判断要求的第i个字符在哪部分里。当第i个字符在第二部分里时这个字符一定是a;当这个字符在第一部分时,继续递归即可;当字符在第三部分时,只要让i减去a[q-1]的长度和q-1即可。

具体代码实现如下:

#include<bits/stdc++.h>
using namespace std;
int a[1000]={0,3},q=1,t,c,a1,hzk;
char b[10]={' ','c','a','t'};
void dfs(int x){//把整个基因分成三部分,第一部分是原来的基因,第二部分是添加的t-1个a,第三部分是复制的基因 
	if(x<=3){//如果只剩下三个以内的字符 
		hzk=x;//记录 
		return;
	}
	if(x<=a[q-1]){//如果在第一部分中 
		q--;
		dfs(x);//继续递归 
	}
	else if(x>a[q-1]&&x<=a[q]-a[q-1]){//如果在第二部分中 
		hzk=2;//第二部分的字符只能是a,直接记录并跳出递归 
		return;
	}
	else if(x>a[q]-a[q-1]){//如果在第三部分中 
		q--;
		dfs(x-a[q]-q);//把所要求的位置减去上一秒的基因长度和刚刚添加的a的长度,相当于把它放到第一部分中相应的字符的位置 
	}
}
int main()
{
	freopen("cat.in","r",stdin);
	freopen("cat.out","w",stdout);
	cin>>t;
	for(int i=1;i<=t;i++)
	{
		cin>>c;
		while(a[q]<c) a[++q]=a[q-1]*2+q-1;//求出当第q次时,基因长度大于输入的c 
		a1=q;
		dfs(c);
		cout<<b[hzk]<<' '<<a1<<endl;
		q=1;
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

朝三暮四:(n只猴子分m个栗子,求方案数)

首先,要让m只猴子都有栗子,所以这个题目相当于让m只猴子分n-m个栗子(可以有某只猴子没有分到第二颗栗子),因为猴子是一样的,所以有状态转移方程dp[i][j][k]=dp[i-1][j-k][0]+dp[i-1][j-k][1]+...............+dp[i-1][j-k][k](其中i是指第i值猴子,j是指第j个栗子,k是指这只猴子至少分配到的栗子数)

具体递归代码如下:

 

#include<bits/stdc++.h>
using namespace std;
int n,m;
inline int dfs(int x,int y)
{
	if(x<=1||y<=1) return 1;//如果只剩下一只猴子或者一个栗子,那么就有了一种方法
	else if(x<y) return dfs(x,x);//如果栗子数小于猴子数,那么就不可能给每个猴子都分栗子,所以分的方案数等于用x个栗子分给x个猴子的方案数
	else
	{ 
	    if(x==y) return dfs(x,x-1)+1;//如果猴子数和栗子数相同,那么让一只猴子不拿栗子
	    else return dfs(x,y-1)+dfs(x-y,y);//如果猴子数小于栗子数,那么可以让每只猴子都多拿一个栗子或者一只猴子不拿栗子 
	}
}
int main()
{
	freopen("monkey.in","r",stdin);
	freopen("monkey.out","w",stdout);
	cin>>n>>m;
	n-=m;//先给每个猴子发一个栗子,保证每只猴子都有栗子; 
	cout<<dfs(n,m)<<endl; 
	fclose(stdin);
	fclose(stdout);
	return 0;
}

望各位大佬不要介意本蒟蒻又臭又长又简略的博客 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值