(JZ3793)2018.07.10【2018提高组】模拟C组 1.【NOIP2014模拟8.20】数字对

【NOIP2014模拟8.20】数字对 (Standard IO)

Description

对于一个数字对(a, b),我们可以通过一次操作将其变为新数字对(a+b, b)或(a, a+b)。
给定一正整数n,问最少需要多少次操作可将数字对(1, 1)变为一个数字对,该数字对至少有一个数字为n。

Input

第一行一个正整数 n

Output

一个整数表示答案。

Sample Input

5

Sample Output

3

Data Constraint

对于30%的数据, 1 <= n <= 1000
对于60%的数据, 1 <= n <= 20000
对于100%的数据,1 <= n <= 10^6

Hint

【样例解释】
(1,1)  →  (1,2)  →  (3,2)  →  (5,2)

题解:

   本题是深度优先搜索
   一开始是想着顺着题目思路的暴力,因为题目要求结果数字对至少有一个数字为n,所以可以表示为(n,x),对于给定的n,用i枚举所有的x,还原(n,i),取最小步数为解,变成(n-i,i),直到还原到(1,1)
   但这个方法很容易会爆,所以我们思考有没有可以简化的方法。考虑到之前是减法,那么多次的减法就是除法了吧(^o^)/
   若a>b,则(a,b)->(a mod b,b),步数+a/b;若b>a,同理可得(但在程序中,我们的设定是a严格大于b的,所以不需要用if来判断╮(╯▽╰)╭)(这样的算法gcd(辗转相除法)很像)

#include<cstdio>
#include<iostream>
#include<algorithm>
const int maxn=233333333;
const int N=1000010;
using namespace std;
int n,ans;
int qiu(int a,int b){
    if (b==1) return a-1;
    if (!b) return maxn;
    return a/b+qiu(b,a%b); //加b步数+剩下步数
}

int main(){
    scanf("%d",&n);
    ans=maxn;
    for (int i=1;i<n;i++) ans=min(ans,qiu(n,i));
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/SSL_lzx/article/details/81007430