这个题非常的不容易 ,第一遍交爆零了
首先根据最大公约数和最小公倍数可知:
这个数x一定包含a1的所有质因数
这个数x一定不包含a0/a1的所有质因数
这个数一定包含b1/b0的所有质因数
这个数可能包含b0的任意个因数
那么显然不同的方案数就是从最后一个“可能”中来,没有方案的情况就是从前三个“一定”中来、
所以可以a1、a0、b1、b0一起分解质因数,然后进行繁琐的判断
码:
#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
ll n,b0,a0,b1,a1,i,ans;
int main()
{
scanf("%lld",&n);
while(n--)
{ ans=0;
scanf("%lld%lld%lld%lld",&a1,&a0,&b0,&b1);
if(b1%a0>0)
{
printf("0\n");
continue;
}
for(i=2;i*i<=b1;i++)
{
if(b1%i)continue;
int lin1=0,lin2=0,lin3=0,lin4=0;
while(!(b1%i))
{
lin1++;
b1/=i;
}
while(!(b0%i))
{
lin2++;
b0/=i;
}
while(!(a0%i))
{
lin3++;
a0/=i;
}
while(!(a1%i))
{
lin4++;
a1/=i;
}
if(lin4-lin3)//必须有a0个
{
//ans*=lin3;
//检验看看fubufu
if(lin1-lin2)//必须有b1个
{
if(lin1==lin3)continue;//放过
else //矛盾
{
ans=-1;
break;
}
}else continue; //相等则可以选用,但必须有a0个,对方案数无贡献,,所以过
}else //必须至少有a0个
{
if(lin1-lin2)//必须有b1个
{
if(lin1>=lin3)continue;//放过
else //矛盾
{
ans=-1;
break;
}
}else //有lin1或lin2个供选择
{
if(ans==0)ans=lin1-lin3;
else ans=ans+ans*(lin1-lin3)+lin1-lin3;
}
}
}
//此刻b1剩下的是最大的单个质因数
if(b1!=1){ if(!(a0%b1)&&a0>1)//如果a0有
{
if(!(a0/b1%b1)&&a0/b1>1)//如果a0有多个 那你就完了
ans=-1;
} //如果a0没有,就无所谓了 若a0没有,则a1可能有 a1有就
else{
if(b0%b1) //如果b0没有,而a1有 那就出事了
{if(!(a1%b1)&&a1>1)ans=-1;
}else {
if(!(a1%b1)&&a1>1);
else{
if(ans==0)ans=1; //
else ans=ans+ans+1;
}
}
}
}
if(ans>=0) printf("%d\n",ans+1);
else printf("0\n");
}
}
ps:这个题刚进新校的时候考过,当时折腾了4h没搞出来
没有用任何新知识,但现在终于能搞出来了
主要还是对gcd 和lcm 、质数、质因数的理解和逻辑思维、、
提高对某些知识点的理解还是很重要的、、、、