[Luogu 2090]数字对

Description

对于一个数字对(a, b),我们可以通过一次操作将其变为新数字对(a+b, b)或(a, a+b)。

给定一正整数n,问最少需要多少次操作可将数字对(1, 1)变为一个数字对,该数字对至少有一个数字为n。

Input

第一行一个正整数 n

Output

一个整数表示答案。

Sample Input

5

Sample Output

3

Hint

样例解释:

(1,1)  →  (1,2)  →  (3,2)  →  (5,2)

对于30%的数据, 1 <= n <= 1000

对于60%的数据, 1 <= n <= 20000

对于100%的数据,1 <= n <= 10^6

题解

我们注意到对于数对$(x,y)$,$x>y$,一定是由$(x-y,y)$推得的,我们发现就是更相减损术。

我们可以枚举$<n$的所有数,做一遍$gcd$,统计操作次数。

最终,如果其中一个数为$1$,那么我们可以去更新一下答案;

但如果为$0$,即最初始数对不合法,舍去。

 1 #include<set>
 2 #include<map>
 3 #include<cmath>
 4 #include<ctime>
 5 #include<queue>
 6 #include<stack>
 7 #include<vector>
 8 #include<cstdio>
 9 #include<string>
10 #include<cstdlib>
11 #include<cstring>
12 #include<iostream>
13 #include<algorithm>
14 using namespace std;
15 
16 int n,cnt;
17 int gcd(int a,int b)
18 {
19     int cnt=0;
20     while (true)
21     {
22         if (b==0) return 0;
23         if (b==1) 
24         {
25             cnt+=a-1;
26             break;
27         }
28         cnt+=a/b;
29         a%=b;
30         swap(a,b);
31     }
32     return cnt;
33 }
34 
35 int main()
36 {
37     scanf("%d",&n);
38     int ans=~0u>>1;
39     if (n==1) printf("0
");
40     else
41     for (int i=1;i<n;i++)
42     {
43         int cnt=gcd(n,i);
44         if (cnt) ans=min(ans,cnt);
45     }
46     printf("%d
",ans);
47     return 0;
48 }
原文地址:https://www.cnblogs.com/NaVi-Awson/p/7448204.html