算法:辗转相除(欧几里得)
gcd(a, b)是a和b最小公倍数, lcm(a, b)是a和b的最大公倍数
gcd(a, b) == gcd(b, a%b)
时间复杂度: O(lgb)
具体证明很多的,百度即可。
代码:
int gcd(int a, int b){return (b?gcd(b, a%b):a);}
(非递归版自己推)
lcm(a, b) = a*b/gcd(a, b)
这里要注意个细节优化,在程序中应该防止溢出,即要写成
lcm(a, b) = a/gcd(a, b)*b
时间复杂度:O(lgb)
代码:
inline int lcm(int a, int b){return a / gcd(a, b) * b;}
好了到此题:【wikioi】1012
14.01.02 PS: 这是之前的代码,有点不简洁。
一般枚举算法
//暴力枚举即可 //只不过gcd(a, b) == gcd(b, a%b); lcm(a, b) == a/gcd(a, b)*b; #include <iostream> using namespace std; int mymin, mymax; void gcd(const int &a, const int &b){if(a%b==0) mymin=b; else gcd(b, a%b);} inline int lcm(const int &a, const int &b){return (a/mymin)*b;} int main() { int tmin, tmax; cin >> tmin >> tmax; int ans = 0; for(int i = tmin; i <= tmax; i++) { if(i % tmin != 0 || tmax % i != 0) continue; for(int j = tmin; j <= tmax; j++) { if(j % tmin != 0 || i * j < tmax || tmax % j != 0) continue; gcd(i,j); if(mymin != tmin) continue; mymax = lcm(i, j); if(mymax != tmax) continue; ans++; } } cout << ans << endl; return 0; }