外星猫:(一只猫,原来的基因是“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;
}
望各位大佬不要介意本蒟蒻又臭又长又简略的博客