题意:n组询问,每组给定四个正整数a0,a1,b0,b1, 求满足gcd(x,a0) = a1, lcm(x,b0) = b1的x的个数。
输入格式:
第一行,一个正整数n;
第二行,四个正整数a0,a1,b0,b1;
输出格式:
共n行,每行一个正整数,表示满足条件的x的个数。
样例输入:
2
41 1 96 288
95 1 37 1776
样例输出:
6
2
解析:一道简单的数学题。先来看一个简单的定理,gcd(a,b) = c, 则gcd(a/c,b/c) = 1. 定理的正确性很显然,在本题中,要求gcd(x,a0) = a1,即是gcd(x/a1,a0/a1) = 1。又要求lcm(x,b0)=b1,而lcm(x,b0) = x*b0/gcd(x,b0), 所以gcd(x,b0) = x*b0/lcm(x,b0). 因为lcm(x,b0) = b1,所以gcd(x,b0) = x*b0/b1. 同理,gcd(x/(x*b0/b1),b0/(x*b0/b1)) = 1,化简可得gcd(b1/b0,b1/x) = 1. 推到了这里,我们得到了两个式子,即gcd(x/a1,a0/a1) = 1,gcd(b1/b0,b1/x) = 1。可以发现x为a1的倍数,并且为b1的因数。所以我们只需要枚举b1的每个因子,再进行判断便可,复杂度o(n√b1)。
代码如下:
#include<cstdio> #include<cmath> using namespace std; int n,a0,a1,b0,b1,ans; int read(void) { char c; while (c=getchar(),c<'0' || c>'9'); int x=c-'0'; while (c=getchar(),c>='0' && c<='9') x=x*10+c-'0'; return x; } int gcd(int x,int y) { //求gcd if (y==0) return x; else return gcd(y,x%y); } int main() { n=read(); while (n--) { ans=0; a0=read(); a1=read(); b0=read(); b1=read(); for (int i=1;i<=sqrt(b1);++i) { //枚举每个因数 if (!(b1%i)) { //如果是i是b1的因数 if (gcd(b1/b0,b1/i)==1 && i%a1==0 && gcd(i/a1,a0/a1)==1) ans++; if (i==b1/i) continue; //如果因数i与b1/i相等,就continue,防止重复计算 if (gcd(b1/b0,i)==1 && (b1/i)%a1==0 && gcd(b1/i/a1,a0/a1)==1) ans++; } } printf("%d ",ans); } return 0; }