【Hankson 的趣味题】

可能我只适合这道题的50分

但还是要争取一下的

我们知道对于\(gcd\)\(lcm\)有这样的定义

\(a=\prod _{i=1}^{\pi(a)}p_i^{d_{i}}\)

\(b=\prod _{i=1}^{\pi(b)}p_i^{g_{i}}\)

那么则有

\(gcd(a,b)=\prod_{i=1}^{\pi(max(a,b))} p_i^{min(g_i,d_i)}\)

\(lcm(a,b)=\prod_{i=1}^{\pi(max(a,b))} p_i^{max(g_i,d_i)}\)

把上面的式子翻译成汉语就是

如果我们将\(a,b\)质因数分解,那么对于\(a,b\)所有同一个质因子,指数较小的相乘得到的就是\(gcd(a,b)\),指数较大的相乘得到的就是\(lcm(a,b)\)

比如说\(12,8\)

我们分解质因数

\(12=2^2*3^1\)

\(8=2^3\)

所以\(gcd(12,8)=2^{min(2,3)}*3^{min(1,0)}=2^2=4\)

\(lcm(12,8)=2^{max(2,3)}*3^{max(1,0)}=2^3*3^1=24\)

于是有了这个性质,我们做这道题就比较简单了

那我们的核心就是把\(a0,a1,b0,b1\)都分解质因数

之后对于相同的质因子我们都要讨论一下他的指数,来推出\(x\)的指数

如果有解的话,这个指数必定是一个范围,所以我们可以求出每个指数的范围之后乘法原理得出答案

如果无解我们就中途判断推出就好了

但是还有一个问题,我们分解质因数的话应该怎么分解,分解到一个什么范围

我们知道整数还有一个一个性质:每个整数\(n\)至多有一个大于\(\sqrt{n}\)的质因子

尽管这里的数都很大,小于等于\(2E9\)但是我们只需要筛出\(1\)\(\sqrt{2E9}\)之间的质数,剩下的那个质因子我们特判就可以了

代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<bitset>
#define LL long long
#define re register
#define maxn 50005
using namespace std;
int T;
int p[maxn],tot;
bitset<maxn> f;
LL a0,a1,b0,b1;
inline LL read()
{
	char c=getchar();
	LL x=0;
	while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9')
	  x=(x<<3)+(x<<1)+c-48,c=getchar();
	return x;
}
int main()
{
	T=read();
	f[1]=1;
	for(re int i=2;i<=maxn-5;i++)
	{
		if(!f[i]) p[++tot]=i;
		for(re int j=1;j<=tot&&p[j]*i<=maxn-5;j++)
		{
			f[p[j]*i]=1;
			if(i%p[j]==0) break;
		}
	}//欧拉筛,由于sqrt(2000000000)大概为45000,所以筛到50000就可以了
	while(T--)
	{
		LL ans=1;
		int flag=0;
		a0=read();
		a1=read();
		b0=read();
		b1=read();
		for(re int i=1;i<=tot;i++)
		{
			if(a0==1&&a1==1&&b0==1&&b1==1) break;
			int num1=0,num2=0,num3=0,num4=0;
			while(a0%p[i]==0) num1++,a0/=p[i];
			while(a1%p[i]==0) num2++,a1/=p[i];
			while(b0%p[i]==0) num3++,b0/=p[i];
			while(b1%p[i]==0) num4++,b1/=p[i];
            //统计这个质因子对应的指数应该是多少
			if(num1<num2||num3>num4) //如果这个a0质因子的指数小于a1的,那么就无解,因为a1的指数应该是最小的
 //如果这个b0质因子的指数大于b1的,那么就无解,因为b1的指数应该是最大的
			{
				flag=1;
				break;
			}
			if(num3<num4) 
            //如果b0的指数小于b1的,说明x此时的指数应该为num4,所以此时对答案没有贡献,判断是否有解之后退出
			{
				if(min(num4,num1)!=num2)
				{
					flag=1;
					break;
				}
				continue;
			}
			if(num1>num2)
            //如果a0的指数大于a1的,说明x此时的指数应该为num2,所以此时对答案没有贡献,判断是否有解之后退出
			{
				if(max(num2,num3)!=num4)
				{
					flag=1;
					break;
				}
				 continue;
			}
			if(num3<num1)
			{
				flag=1;
				break;
			}
			ans=ans*(num3-num1+1);
		}
		if(!flag&&(a1!=1||a0!=1||b0!=1||b1!=1))
		{
			if(a1>a0) flag=1;
			if(b1<b0) flag=1;
			if(b1==b0&&b1!=1) ans<<=1;
		}
		if(!flag) cout<<ans<<endl;
		else puts("0");
	}
}
posted @ 2019-01-02 12:04  asuldb  阅读(206)  评论(0编辑  收藏  举报