Hanks 博士是 BT(Bio-Tech,生物技术)领域的知名专家,他的儿子名叫 Hankson。现在,刚刚放学回家的 Hankson 正在思考一个有趣的问题。

今天在课堂上,老师讲解了如何求两个正整数 c_1c 1 和 c_2c 2
的最大公约数和最小公倍数。现在 Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数 a_0,a_1,b_0,b_1a 0 ,a 1​ ,b 0​ ,b 1​ ,设某未知正整数x满足:xx 和 a_0a 0​ 的最大公约数是 a_1a 1
​ ;xx 和 b_0b 0​ 的最小公倍数是 b_1b 1 。
Hankson 的“逆问题”就是求出满足条件的正整数 xx 。但稍加思索之后,他发现这样的 xx 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的 xx 的个数。请你帮助他编程求解这个问题。
输入格式
第一行为一个正整数 nn ,表示有 nn 组输入数据。接下来的 nn 行每行一组输入数据,为四个正整数 a_0a
0​ ,a_1a
1​ ,b_0b
0​ ,b_1b 1​ ,每两个整数之间用一个空格隔开。输入数据保证 a_0a
0​ 能被 a_1a 1​ 整除,b_1b 1​ 能被 b_0b ​ 整除。

输出格式
对于每组数据:若不存在这样的 xx ,请输出 00;

若存在这样的 xx ,请输出满足条件的 xx 的个数;

数据范围
对于 50%50% 的数据,保证有 1 \le a_01≤a
0

,b_1b
1

,b_0b
0

,b_1 \le 10000b
1

≤10000 且 n \le 100n≤100。

对于 100%100% 的数据,保证有 1 \le a_01≤a
0

,b_1b
1

,b_0b
0

,b_1 \le 2,000,000,000b
1

≤2,000,000,000 且 n \le 2000n≤2000。

样例说明
第一组输入数据,xx 可以是 99、1818、3636、7272、144144、288288,共有 66 个。

第二组输入数据,xx 可以是 4848、17761776,共有 22 个。

输出时每行末尾的多余空格,不影响答案正确性

样例输入复制
2
41 1 96 288
95 1 37 1776
样例输出复制
6
2

解题思路:将a,b,c,d分解质因数存起来,用map存,然后枚举每个质数的t次,利用两个数质因子指数最小值等于约数的质因子指数,两个数的质因子的最大值等于最小公倍数的质因子指数,就好了。这题小技巧,用map<int,node> first代表质因子,node代表结构体里面存a,b,c,d

	#include<iostream>
	#include<algorithm>
	#include<cstdio>
	#include<cstring>
	#include<cmath>
	#include<map>
	#include<vector>
	#include<queue>
	#include<set>
	#define IL inline
	#define x first
	#define y second
	typedef long long ll;
	using namespace std;
	const	int N=1000010;
	struct node{
		int a;
		int b;
		int c;
		int d;
	};
	map<int,node>mp;
	int prime[N],cnt;
	bool st[N];
	void getprime(int n)
	{
		for(int i=2;i<=N;i++)
		{
			if(!st[i])
			prime[cnt++]=i;
			for(int j=0;prime[j]<=N/i;j++)
			{
				st[i*prime[j]]=true;
				if(i%prime[j]==0)
				break;
			}
		}
	}
	int tt[5];
	int main()
	{
		getprime(N);
		int n;
		cin>>n;
		while(n--)
		{
			mp.clear();
			int a,b,c,d;
			cin>>a>>b>>c>>d;
			tt[1]=a,tt[2]=b,tt[3]=c,tt[4]=d;
			for(int idx=1;idx<=4;idx++)	
		{
			int  cc=tt[idx];
			for(int i=0;i<cnt&&(ll)prime[i]*prime[i]<=cc;i++)
			{	
				if(cc%prime[i]==0)
				{
					int cnt=0;
					while(cc%prime[i]==0)
					{
						cc/=prime[i];
						cnt++;
					}
					if(idx==1)
					mp[prime[i]].a=cnt;
					if(idx==2)
					mp[prime[i]].b=cnt;
					if(idx==3)
					mp[prime[i]].c=cnt;
					if(idx==4)
					mp[prime[i]].d=cnt;
				}		
			}
	 	if(cc>=2)	//判断素数的情况 
			{
					if(idx==1)
					mp[cc].a=1;
					if(idx==2)
					mp[cc].b=1;
					if(idx==3)
					mp[cc].c=1;
					if(idx==4)
					mp[cc].d=1;			
			}
				}
			long long res=1;
			for(auto it:mp){
				int cnt=0;
			for(int j=0;j<=31;j++)
			{
				node t=it.second;
				int a=t.a,b=t.b,c=t.c,d=t.d;
				if(min(j,a)==b&&max(c,j)==d)
				cnt++;
			}
			res = res * cnt;
			}
			cout<<res<<endl;
		}
	    return 0;
	}