题目大意:
对于一个数字对(a,b)(a,b),可以将其变为新数字对(a+b,b)(a+b,b)或(a,a+b)(a,a+b)。
给定一正整数n,问最少需要多少次操作可将数字对(1,1)(1,1)变为一个数字对,且该数字对有一个为n。
思路:
真的不会做啊。。。
考试时想了bfsbfs,dfsdfs,DPDP,但是都至少是O(n2)O(n2)的算法,对于n≤106n≤106根本吃不消。
最后还是打了一个DPDP灰溜溜的交上去,30分。
正解:数论,GCDGCD
有谁看得出这是GCDGCD的题目???
对于给定的nn,我们可以枚举所有的,模拟还原(n,i)(n,i),最终步数最少的就是最终解。
这道题可以类比求gcdgcd的辗转相除法。
若 a>ba>b,则gcd(a,b)=gcd(amodb,b)gcd(a,b)=gcd(amodb,b)
若 a≤ba≤b,则gcd(a,b)=(a,bmoda)gcd(a,b)=(a,bmoda)
当达到一定次数时,b=1b=1,那么这就是一个合法的解。如果b=0b=0时,bb没有等于过,那么这个解就不合法。
代码:
#include <cstdio>
#include <iostream>
using namespace std;
int n,ans;
int gcd(int a,int b) //辗转相除法
{
if (!b) return 99999999; //b到达0且没有等于过1,无解
if (b==1) return a-1; //b=1,有借
return gcd(b,a%b)+a/b;
}
int main()
{
scanf("%d",&n);
ans=99999999;
for (int i=1;i<=(n+1)/2+1;i++) //简单精简。
ans=min(ans,gcd(n,i));
return printf("%d\n",ans)&0;
}