題目:已知兩個數的最小公倍數和其中一個數,求另一個數。
分析:數論,構造。本題可以才用枚舉的方式求解,這裡利用數論的方法。
設a = g * A0,b = g * B0,其中gcd(A0, B0) = 1;
如果gcd(c/A0, A0) = gcd(B0 * g, A0) = 1,则b = B0可以滿足題意;
否則gcd(c/A0, A0) = gcd(B0 * g, A0) = gcd(B0 * g0 * g', A1 * g0) = g0;
此時取B1 = B0 * g0,則有 lcm(a, b) = A0 * B0 * g = A1 * B1 * g;
(如果取b = B0,則lcm(a, b) = A1 * B0 * g = A0 * B0 * g' 与假设矛盾)
如果gcd(c/A1, A1) = gcd(A0 * B0 * g / A1, A1) = gcd(g * g' * B0, A1) = 1,則b = B1滿足題意;
否則,繼續迭代求出B2,A2,直到gcd(c/Ak, Ak) = 1;(时间复杂度为(lgN)^2);
說明:本題使用構造方法求解,其正確性在構造結束時即被證明。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int gcd(int a, int b)
{
return a%b?gcd(b, a%b):b;
}
int main()
{
int t,a,c;
while (~scanf("%d",&t))
while (t --) {
scanf("%d%d",&a,&c);
if (c%a)
printf("NO SOLUTION\n");
else {
int g = 1;
do {
a = a/g;
g = gcd(c/a, a);
}while (g != 1);
printf("%d\n",c/a);
}
}
return 0;
}