一个JSB做法
由$\frac{x*b0}{gcd(x,b0)}=b1$,可得$\frac{x}{gcd(x,b0)}=\frac{b1}{b0}$
设$b2=\frac{b1}{b0}$
所以对$b2$和$b0$分解质因数,可以得到结论:
1.x必须包含b2中所有的质因数,且个数等于它在b2和b0(如果b0中有的话)中的数量和
2.对于b0中有但b2中没有的质因数,x中它的个数可以是[0,b0中的个数]
然后关于a0和a1,也有结论:
1.x中必须包含a1中的所有质因数
2.x中不能包含a0中的、a1以外的(在数量和种类方面)质因数
然后就可以开始乱搞了
首先打出1e5以内的素数,然后拿着它们分解质因数(因为我只需要做到$\sqrt{N}$)。注意一个数如果最后剩下不是1,那么剩下这个数也是个质因数(大于$\sqrt{N}$)
然后把这些存到set里,按照上面的规则乱搞......
一个数最多大概也就十几种质因数,所以复杂度没什么问题。
#include<bits/stdc++.h>
#define pa pair<int,int>
#define IT set<pa>::iterator
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=1e5+,inf=2e9+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} bool ispri[maxn];
int pri[maxn],pct;
set<pa> g[]; inline void get(int id,int x){
g[id].clear();
for(int i=;x>&&i<=pct;i++){
if(x<pri[i]) break;
if(x%pri[i]) continue;
int cnt=;
while(x%pri[i]==) x/=pri[i],cnt++;
g[id].insert(make_pair(pri[i],cnt));
}
if(x!=) g[id].insert(make_pair(x,)); } int main(){
int i,j;
int N=rd();
CLR(ispri,);ispri[]=ispri[]=;
for(i=;i<=;i++){
if(ispri[i]){
for(j=i+i;j<=;j+=i){
ispri[j]=;
}
}
}for(i=,j=;i<=;i++) if(ispri[i]) pri[++pct]=i;
for(i=;i<=N;i++){
int a1=rd(),a2=rd(),b1=rd(),b2=rd();
int b3=b2/b1;
get(,a1);get(,a2);get(,b1);get(,b3);
g[].clear();
for(IT it=g[].begin();it!=g[].end();it++){
IT it2=g[].lower_bound(make_pair(it->first,-));
if(it2->first!=it->first) g[].insert(make_pair(it->first,));
else if(it2->second!=it->second) g[].insert(make_pair(it->first,it2->second));
else g[].insert(make_pair(it->first,-it2->second));
}
int ans=;
for(IT it=g[].begin();it!=g[].end();it++){
IT it2=g[].lower_bound(make_pair(it->first,-inf));
IT it3=g[].lower_bound(make_pair(it->first,-inf));
if(it->second&&it2->first!=it->first&&it3->first!=it->first) ans=;
if(it->first==it3->first&&it2->first!=it->first&&((it->second>=&&it3->second!=it->second)||(it->second<&&(-it->second)>it3->second))) ans=;
}
if(!ans) {printf("0\n");continue;}
for(IT it=g[].begin();it!=g[].end()&&ans;it++){
IT it2=g[].lower_bound(make_pair(it->first,-inf));
IT it3=g[].lower_bound(make_pair(it->first,-inf));
if(it2->first!=it->first){
if(it3->first!=it->first) ans*=it->second+;
else if(abs(it3->second)>it->second) ans=;
else if(it3->second<) ans*=it->second+it3->second+;
}else{
if(it3->first!=it->first);
else if(it3->second>=&&it3->second!=it2->second+it->second) ans=;
else if(it3->second<&&it2->second+it->second<-it3->second) ans=;
}
}
printf("%d\n",ans);
}
return ;
}