poj1207~递归和打表

本文介绍了一种通过递归及部分预计算的方法来解决求解指定区间内数字的特定循环序列的最大长度问题。该方法避免了完全预计算,以减少内存使用。

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

题意比较难懂

一个数字x,如果是奇数则x=x*3+1,否则x=x/2.,直到x=1,这个过程所经过的长度叫做“循环数”

题目给你2个数字i和j,求i和j区间中最大的循环数。

i可能大于j!

我的思路就是递归加打表,不过打表不能全打,因为范围可能会超大,比如(9999*3+1)=29998有点大啊,为了防止超出我的预想打表的时候定个范围

#include<iostream>
#include<string>    
#include<queue>
#define M 10005
using namespace std;
int vis[M],num[M];

int dfs(int x)
{
	int y,ans;
	if(x<M&&vis[x]==1) return num[x];  //x<M防止数组越界,超出的就不打表了,直接算
	if(x==1) return 1;         
	
	if(x%2==1)
		y=x*3+1;
	else y=x/2;
	
	ans=1+dfs(y);
	if(x<M)     //小于M就打表
	{
		num[x]=ans;
		vis[x]=1;
	}
	return ans;
	
}

int main()
{
	int i,a,b,max,t;
	memset(vis,0,sizeof(vis));
	num[1]=1;
	while(scanf("%d%d",&a,&b)!=EOF)
	{
		max=0;
		printf("%d %d ",a,b);
		if(a>b)         //陷阱!a不一定小于b
		{
			t=a;
			a=b;
			b=t;
		}
		for(i=a;i<=b;i++)
		{
			dfs(i);
			if(num[i]>max)
				max=num[i];
		}
		printf("%d\n",max);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值