洛谷 P1635 跳跃

题目:

题目背景

NOIP即将迎来周年华诞。在这一个春秋的历程里,NOIP领导全国oier,建设高效、稳定、快捷、开放的社会主义现代化OI。在新的一年里,YZOJ将再接再厉,积极探寻成长之路,更好地为广大oier服务。

题目描述

青蛙小C听说NOIP要办周年庆比赛,兴冲冲得来到了Z市,初始时他在坐标x0处,小C是一只善于跳跃的青蛙,若当前他处在坐标x处,每一次跳跃,他可以跳到4x+34x+34x+38x+78x+78x+7处,且由于体力原因,他最多能跳100000100000100000次。根据Z市的传说,坐标位置为100000000710000000071000000007的整数倍的位置(如100000000710000000071000000007200000001420000000142000000014)可以传送到YZOJ。小C想知道,最少跳几次能传送到YZOJ。

输入输出格式

输入格式:

输入的第一行包含一个整数x0表示青蛙的初始位置,保证x0在的范围在[1,1000000006][1,1000000006][1,1000000006]

输出格式:

输出一个整数,表示最少所需步数,若在100000100000100000步内还无法传送到YZOJYZOJYZOJ,则输出−1-11

分析:

显然,这一看就是一道数学题

那么我们怎么考虑呢?

如果你细心一点就会发现:

4x+3=2∗(2x+1)+14x+3=2*(2x+1)+14x+3=2(2x+1)+1

8x+7=2∗(2∗(2x+1)+1)+18x+7=2*(2*(2x+1)+1)+18x+7=2(2(2x+1)+1)+1

那么不就是说,只需要计算与2x+1有关的步数,然后推导普遍规律就行。

计算有几次2x+1的过程太简单,等会直接看代码就行。下面分析处理结果的方法。

再跳回两个式子:

4x+3=2∗(2x+1)+14x+3=2*(2x+1)+14x+3=2(2x+1)+1

8x+7=2∗(2∗(2x+1)+1)+18x+7=2*(2*(2x+1)+1)+18x+7=2(2(2x+1)+1)+1

我们可以发现:最多的是由三个2x+1等构成(即8x+7),所以我们不妨考虑将结果先mod 3:

  • %3=03=03=0:那么就是一堆8x+78x+78x+7(设为n个),输出answer/3;answer/3;answer/3;

  • %3=13=13=1:可以想成把本来的nnn8x+78x+78x+7从整好的多了一个2x+12x+12x+1,所以只能拆出一个2x+12x+12x+1,变成n−1n-1n18x+78x+78x+72224x+34x+34x+3.

  • %3=23=23=2:可以想成把本来的n个8x+78x+78x+7从整好的多了两个2x+12x+12x+1,所以n个8x+78x+78x+7不用变,只是把多出的两个2x+12x+12x+1合成一个4x+34x+34x+3就行。

对了补充一句,因为首先是给出x,然后才能变成2x+1,4x+3,8x+7 . 等。所以所谓的三步其实是算上x变成2x+1的QAQ

然后归纳一下就行了,具体看代码:

#include<cstdio> 
using namespace std; 
const int mod=1000000007;//定义mod
int ans;
int search(int x)//递归部分,AC
{
	if(ans>=300100)//由于每次递归做的次数都很少,所以可以多做几次,避免误差
	{
		printf("-1");
		return 0;
	}
	int y=((x%mod)*2+1)%mod;
	ans++;
	if(y==0)//等于0就是达成了整数倍
	{//接下来就是归纳刚刚分析的内容,中间要判断答案是否在100000以内
		if(ans%3==0)
		{
			if(ans/3>100000)
			{
				printf("-1");
				return 0;
			}
			printf("%d",ans/3);
			return 0;
		}
		else
		{
			if(ans/3+1>100000)
			{
				printf("-1");
				return 0;
			}
			printf("%d",ans/3+1);
			return 0;
		}
	}
	else
	search(y);//继续走
	return 0;
}
int main()
{ 
	long long m; 
	scanf("%lld",&m);
	
	/*while(ans<=300000)//非递归部分,暂时没有AC
	{ 
		m=m*2+1;
		ans++;
		if(m%1000000007==0)
		{
			if(ans>100000)
			{
				printf("-1\n");
			}
			if(ans%3==0)
			printf("%d",ans/3);
			else
			{
				printf("%d",ans/3+1);
			}
			return 0;
		}
	} 
	printf("-1\n"); */
	search(m);
	return 0; 
} 
全部评论

相关推荐

昨天 18:27
已编辑
门头沟学院 C++
26学院本太难了,很多公司机筛就给我刷了。机会都难拿到如果是简历存在问题也欢迎拷打————————————————————分割线——————————————————————2026.3.4更新:发完贴之后,时不时投递又收到了不少的笔试/面试邀请。主要是之前投递简历出去之后基本上都是沉默状态,年后好转了不少timeline:2026.01.21&nbsp;文远知行笔试,半年多没刷算法题&nbsp;-&gt;挂&nbsp;(后续HR说春招可以重新安排笔试)2026.2.4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;小鹏汇天&nbsp;技术一面,第二周收到结果&nbsp;-&gt;挂2026.2.12&nbsp;&nbsp;&nbsp;大众Cariad代招&nbsp;技术二面&nbsp;-&gt;Offer2026.2.28&nbsp;&nbsp;&nbsp;多益网络技术面试,由于风评太差,一直在犹豫要不要接面试&nbsp;-&gt;推迟-----------分割线-----------2026.3&nbsp;月前的某一天,临时去电网报名了二批计算机岗位的笔试2026.3.6&nbsp;从上家公司实习离职,氛围最好的一家公司,leader&nbsp;说可以帮忙转正,但是流程太长,而且我们部门据说只有一个&nbsp;hc,更想要研究生,我很有可能是会被签外包公司在这里干活,就离职了。2026.3.9&nbsp;入职新公司,大众Cariad&nbsp;以外部公司的身份进组,项目组签了三年,后续三年应该都可以在这里呆,不知道有没有希望原地跳槽。2026.3.10&nbsp;电网考试居然说我通过资格审查了,短信约我去参加资格审查,请假一天,买了&nbsp;12&nbsp;号晚上的机票回成都2026.3.15&nbsp;参加国家电网三新计算机类的笔试2026.3.17&nbsp;电网出成绩了,感觉很低。觉得已经🈚️了2026.3.18&nbsp;收到电网面试通知,通知&nbsp;3.22-3.25&nbsp;这个时间去面试,我的岗位只招&nbsp;1&nbsp;个人。据说面试只有&nbsp;2-3&nbsp;人,不知道能不能成功
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务