【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\)
比如說\(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"); } }