今天在课堂上,老师讲解了如何求两个正整数c_1c1 和 c_2c2 的最大公约数和最小公倍数。现在 Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a_0,a_1,b_0,b_1a0,a1,b0,b1,设某未知正整数xx 满足:
1. xx 和 a_0a0 的最大公约数是 a_1a1;
2. xx 和 b_0b0 的最小公倍数是b_1b1。
Hankson 的“逆问题”就是求出满足条件的正整数xx。但稍加思索之后,他发现这样的xx 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的 xx 的个数。请你帮助他编程求解这个问题。
【数据范围】
对于 50%的数据,保证有 1≤a_0,a_1,b_0,b_1≤100001≤a0,a1,b0,b1≤10000 且n≤100n≤100。
对于 100%的数据,保证有 1≤a_0,a_1,b_0,b_1≤2,000,000,0001≤a0,a1,b0,b1≤2,000,000,000 且 n≤2000n≤2000。
NOIP 2009 提高组 第二题
1、x的质因子的范围
2、别忘了 sqrt(b1)之后还有可能的因子
ll n,a0,a1,b0,b1;
bool isp[maxn];
ll prime[maxn];
ll cnt=0;
ll gcd(ll a,ll b){
if(b==0)return a;
return gcd(b,a%b);
}
ll lcm(ll a,ll b){
return a*b/(gcd(a,b));
}
void run(ll x,ll &res,ll k){
res=0;
while(x%k==0){
res+=1;
x/=k;
}
}
signed main() {
#ifdef local
freopen("input2.txt","r",stdin);
#endif //local
ll shangjie=sqrt(9e9);
mem(isp,1);
for(ll i=2;i<=shangjie;i++){
if(isp[i]){
prime[cnt++]=i;
for(ll j=i+i;j<=shangjie;j+=i){
isp[j]=0;
}
}
}
cin>>n;
for(ll i=1;i<=n;i++){
cin>>a0>>a1>>b0>>b1;
int tt=sqrt(b1);
ll ans=1;
ll b1b1=b1;
for(ll j=0;j<cnt;j++){
if(b1b1%prime[j])continue;
//b1b1%=prime[j];
ll tem=prime[j];
while(b1b1%tem==0){
b1b1/=tem;
}
ll cnta0,cnta1,cntb0,cntb1;
run(a0,cnta0,tem);
run(a1,cnta1,tem);
run(b0,cntb0,tem);
run(b1,cntb1,tem);
// cout<<cnta0<<cnta1<<cntb0<<cntb1<<en;
ll l=0;ll r=inf;
if(cnta0<cnta1){
ans=0;
break;
}
if(cnta0==cnta1){
l=max(l,cnta1);
}
if(cnta0>cnta1){
r=min(r,cnta1);
l=max(l,cnta1);
}
if(cntb0>cntb1){
ans=0;
break;
}
if(cntb0==cntb1){
r=min(r,cntb1);
}
if(cntb0<cntb1){
l=max(l,cntb1);
r=min(r,cntb1);
}
if(l>r){
ans=0;
break;
}else{
ans*=(r-l+1);
}
}
if(b1b1!=1){
ll tem=b1b1;
// while(b1b1%tem==0){
// b1b1/=tem;
// }
ll cnta0,cnta1,cntb0,cntb1;
run(a0,cnta0,tem);
run(a1,cnta1,tem);
run(b0,cntb0,tem);
run(b1,cntb1,tem);
// cout<<cnta0<<cnta1<<cntb0<<cntb1<<en;
ll l=0;ll r=inf;
if(cnta0<cnta1){
ans=0;
break;
}
if(cnta0==cnta1){
l=max(l,cnta1);
}
if(cnta0>cnta1){
r=min(r,cnta1);
l=max(l,cnta1);
}
if(cntb0>cntb1){
ans=0;
break;
}
if(cntb0==cntb1){
r=min(r,cntb1);
}
if(cntb0<cntb1){
l=max(l,cntb1);
r=min(r,cntb1);
}
//cout<<tem<<' '<<l<<' '<<r<<en;
if(l>r){
ans=0;
break;
}else{
ans*=(r-l+1);
}
}
cout<<ans<<en;
}
//cout<<res<<en;
}