題目鏈接:http://lx.lanqiao.cn/problem.page?gpid=T99
1 題目
題目描述
Hanks 博士是BT (Bio-Tech,生物技術) 領域的知名專家,他的兒子名叫Hankson。現在,剛剛放學回家的Hankson 正在思考一個有趣的問題。 今天在課堂上,老師講解了如何求兩個正整數c1 和c2 的最大公約數和最小公倍數。現 在Hankson 認爲自己已經熟練地掌握了這些知識,他開始思考一個“求公約數”和“求公 倍數”之類問題的“逆問題”,這個問題是這樣的:已知正整數a0,a1,b0,b1,設某未知正整 數x 滿足: 1. x 和a0 的最大公約數是a1; 2. x 和b0 的最小公倍數是b1。 Hankson 的“逆問題”就是求出滿足條件的正整數x。但稍加思索之後,他發現這樣的 x 並不唯一,甚至可能不存在。因此他轉而開始考慮如何求解滿足條件的x 的個數。請你幫助他編程求解這個問題。
輸入格式
輸入第一行爲一個正整數n,表示有n 組輸入數據。
接下來的n 行每 行一組輸入數據,爲四個正整數a0,a1,b0,b1,每兩個整數之間用一個空格隔開。輸入 數據保證a0 能被a1 整除,b1 能被b0 整除。
輸出格式
輸出共n 行。每組輸入數據的輸出結果佔一行,爲一個整數。
對於每組數據:若不存在這樣的 x,請輸出0; 若存在這樣的 x,請輸出滿足條件的x 的個數;
樣例輸入
2
41 1 96 288
95 1 37 1776
樣例輸出
6
2
樣例說明
第一組輸入數據,x 可以是9、18、36、72、144、288,共有6 個。
第二組輸入數據,x 可以是48、1776,共有2 個。
2 分析
首先,直接暴力枚舉只能過 的數據。
1.關於兩個定理:
- 最大公約數
int gcd(int a, int b){
return b == 0 ? a : gcd(b, a % b);
}
- 最小公倍數
int lcm(int a, int b){
return a * b / gcd(a, b);
}
2.一個結論:設 ,並有
則 。
證明:
- 假設 ,,並有
- 由假設得:
- 可得 ,結果與題目條件不符,假設不成立
- 則
因此可得:
對於兩個正整數 ,設 則存在
3.推導
- 由最大公約數定理
得
- 由最小公倍數定理
則
得
4.最終可得如下結論:
3 題解
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int gcd(int a, int b){
return b == 0 ? a : gcd(b, a % b);
}
int main(){
int n;
cin >> n;
while(n--){
int a0, a1, b0, b1, ans = 0;
cin >> a0 >> a1 >> b0 >> b1;
for(int x = 1;x <= sqrt(b1);x++){
if(b1 % x == 0){
if(x % a1 == 0 && gcd(x / a1, a0 / a1) == 1 && gcd(b1 / x, b1 / b0) == 1){
ans++;
}
//枚舉另一個因子
int y = b1 / x;
if(y == x){
continue;
}
if(y % a1 == 0 && gcd(y / a1, a0 / a1) == 1 && gcd(b1 / y, b1 / b0) == 1){
ans++;
}
}
}
if(ans != 0){
printf("%d\n", ans);
}else{
printf("0\n");
}
}
return 0;
}