2017年8月12日提高组T2 YMW的数学题

来源:互联网 发布:炫浪网络社区百合 编辑:程序博客网 时间:2024/06/05 14:15

Description


YMW最近迷上了数学,听BPM说,善于思考的孩纸才是好孩纸呢,于是他一边看书,一边开始思考些问题。他看到书上说枚举是最强大的算法,他很不服气,思考片刻,便想出一道题,如果我们有两个正整数a,b,那会有多少对数,满足他们之间的最大公因数是a,最小公倍数是b呢?而你是暴力的最忠实粉丝,你能用枚举进行解决吗?

Input


多组数据,每组数据只有一行,每行两个正整数a,b
以输入文件结束结尾

Output


每组数据输出一个整数,表示符合的有多少对,每组数据占一行

Hint


样例解释,第一组存在4对(3,60),(12,15),(15,12),(60,3),第二组只有(2,2)
数据范围:
不超过100组数据
对于30%的数据2<=a<=2000,2<=b<=2000
对于70%的数据2<=a<=20 0000,2<=b<=20 0000
对于100%的数据2<=a<=20 0000 0000,2<=b<=20 0000 0000

Source


BY BPM

Solution


水题

已知a*b/gcd(a,b)=lcm(a,b),变形得lcm(a,b)*gcd(a,b)=a*b
对于给定的每个gcd和lcm,我们求积并枚举其中一个a,找另一个b

显然这样做还是会T的。不难发现a=gcd(a,b)*k,b=gcd(a,b)*l这样a、b均为gcd的倍数,那么我们枚举gcd前的倍数就可以了

Code


#include <stdio.h>#include <math.h>#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)#define max(x, y) (x)>(y)?(x):(y)#define ll long longinline int gcd(int x, int y){return !y?x:gcd(y,x % y);}int main(void){    int n, m;    while (scanf("%d %d", &n, &m) != EOF){        if (n == m){            puts("1");            continue;        }        ll lim =(ll)(n) * (ll)(m);        int ans = 0;        rep(i, 1, sqrt(lim) / n){            int x = n * i;            int y = lim / x;            ans += (!(lim % x) && gcd(x, y) == n);        }        printf("%d\n", ans * 2);    }    return 0;}
原创粉丝点击