• 洛谷 P1635 跳跃


    题目:

    题目背景

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

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    分析:

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

    那么我们怎么考虑呢?

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

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

    8x+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)+1

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

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

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

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

    • %3=23=2:可以想成把本来的n个8x+78x+7从整好的多了两个2x+12x+1,所以n个8x+78x+7不用变,只是把多出的两个2x+12x+1合成一个4x+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
    ");
    			}
    			if(ans%3==0)
    			printf("%d",ans/3);
    			else
    			{
    				printf("%d",ans/3+1);
    			}
    			return 0;
    		}
    	} 
    	printf("-1
    "); */
    	search(m);
    	return 0; 
    } 
    
  • 相关阅读:
    Oracle:PL/SQL--流程控制——作业练习:向表中循环插入ID编号
    Oracle:PL/SQL--流程控制(三)——循环结构:loop、while-loop、for-loop
    Oracle:PL/SQL--流程控制(三)——循环结构:loop、while-loop、for-loop
    Oracle:PL/SQL--打开控制台or关闭控制台
    Win10远程桌面及防火墙配置
    H3C-Telnet
    网络工程师(软考)心得
    《网络工程师 考前冲刺100题》思维导图
    《2019上半年网络工程师考试大纲》
    网络设计:搭建校园网(组网工程课设)【译】
  • 原文地址:https://www.cnblogs.com/ShineEternal/p/10834326.html
Copyright © 2020-2023  润新知