[GDUT 决赛]--GCD,LCM——我是好人(数论)
Description
众所周知,我是好人!
所以不会出太难的题,题意很简单 给你两个数n和m,问你有多少对正整数对最大公约数是n,最小公倍数是m
最后友情提供解题代码(我真是太好人了)
void solve() { long long n, m; scanf("%lld%lld", &n, &m); int ans = 0; for (long long i = 1; i <= m; i++) { for (long long j = i; j <= m; j++) { if (gcd(i, j) == n && lcm(i, j) == m) ans++; } } printf("%d\n", ans); }
祝大家AC愉快!最好AK,送某扬兑现诺言^_^
Input
输入第1行是一个整数T,表示共T组数据。 接下来是T组数据,每组数据占1行,每一行有2个整数n,m(1 <= n, m <= 10000000000),两个数由一个空格隔开。
Output
结果输出T行,对应T组数据。(T<=100)
每行输出这样的正整数对有多少对(看我多好人,不用你们输出所有整数对)
Sample Input
3 1 1 7 10086 4 16 |
Sample Output
1 0 1 |
解题思路:(1)a,b 两数的最大公约数是n,最小公倍数是m,m 其实就是 n 乘以 a,b 各自特有的因子.那么
肯定就有 m % n ==0 . 换句话说 如果 m % n !=0 那么 输出 就是0;
(2)如果n==m直接输出1,两个数相等且等于m;
(3)设GCD = x,a = k1*x, b = k2*x,因为要使得GCD为x,那么k1,k2要互质,否则的话(假设公因子为c)求得的GCD=x*c,
那么LCM = k1*k2*x,所以m/n=k1*k2,只要找k1,k2满足该式子就行,所以从1开始到根号m/n,找k1*k2=m/n,
且两个互质 即GCD(k1,k2)==1 即可,那么复杂度Tn=O(√(m/n)),注意数据开long long!
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 typedef long long LL; 7 8 LL gcd(LL a, LL b){ 9 return !b ? a : gcd(b, a%b); 10 } 11 LL Search(LL n) 12 { 13 LL i, tmp, cnt = 0; 14 for (i = 1; i <= (double)sqrt(n*1.0); i++){ 15 if (!(n%i)){ 16 //能整除才拆开计算,避免不必要的错误运算 17 tmp = n / i; 18 if (gcd(i, tmp) == 1) cnt++; 19 } 20 } 21 return cnt; 22 } 23 int main() 24 { 25 LL n, m, tmp; 26 int t; 27 scanf("%d", &t); 28 while (t--){ 29 scanf("%lld%lld", &n, &m); 30 if (m%n){ 31 printf("0\n"); 32 continue; 33 } 34 if (n == m){ 35 printf("1\n"); 36 continue; 37 } 38 tmp = m / n; 39 printf("%lld\n", Search(tmp)); 40 } 41 return 0; 42 }
如果这是你所爱的,就不要让自己后悔~~~