洛谷1072 Hankson 的趣味題(素數)
阿新 • • 發佈:2018-11-11
題意
求gcd(a0,x)=a1且lcm(b0,x)=b1中x的解的方案數。
題解
這種gcd的問題一般都要拆成質因數來分析。
線篩出1~sqrt(2e9)中的素數,那麼所有數的質因數一定在其中出現,不然它本身就是一個素數(這個要特判)。
對於質數p,他們的次數分別為ca0,ca1,cb0,cb1。
分析gcd的特點,因為gcd(a0,x)=a1,所以有min(ca0,x)=ca1。具體情況如下:
1、ca0<ca1,無解
2、ca0=ca1,cx>=ca0
3、ca0>ca1,cx=ca1
同理分析lcm,因為lcm(b0,x)=b1,所以max(cb0,x)=cb1。具體分析:
1、cb0>cb1,無解
2、cb0=cb1,cx<cb0
3、cb0<cb1,cx=cb1
結合兩者的情況,會有
1、ca0<cb0 或 cb0>cb1,無解
2、ca0=ca1 且 cb0=cb1,若同時有ca0<=cb0,則cx有cb0-ca0+1個取值方案
3、ca0=ca1 且 cb0<cb1,若同時有ca0<=cb1,則cx有1個取值方案
4、ca0>ca1 且 cb0=cb1,若同時有ca1<=cb0,則cx有1個取值方案
5、ca0>ca1 且 cb0<cb1,若同時有ca1=cb1,則cx有1個取值方案
好了,有了這些就可以打程式碼了,ans等於所有質因數中的取值方案累乘。
程式碼
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int maxn=2010; int tot=0,prime[40000]; int v[50000]; void getprime(int n) { for(int i=2;i<=n;i++) { if(v[i]==0) { v[i]=i; prime[++tot]=i; } for(int j=1;j<=tot;j++) { if(prime[j]*i>n || v[i]<prime[j]) break; v[prime[j]*i]=prime[j]; } } } void get(int &x,int &cnt,int p) { while(x%p==0) { x/=p;cnt++; } } int main() { getprime(sqrt(2e9)+10); int T; scanf("%d",&T); while(T--) { int a0,a1,b0,b1; scanf("%d%d%d%d",&a0,&a1,&b0,&b1); int ca0,ca1,cb0,cb1; int ans=1,cnt; for(int i=1;i<=tot;i++) { ca0=ca1=cb0=cb1=0; get(a0,ca0,prime[i]);get(a1,ca1,prime[i]); get(b0,cb0,prime[i]);get(b1,cb1,prime[i]); if(ca0==ca1 && cb0==cb1 && ca0<=cb0) cnt=cb0-ca0+1; else if(ca0==ca1 && cb0<cb1 && ca0<=cb1) cnt=1; else if(ca0>ca1 && cb0==cb1 && ca1<=cb0) cnt=1; else if(ca0>ca1 && cb0<cb1 && ca1==cb1) cnt=1; else{ans=0;break;} ans*=cnt; } if(ans!=0)//如果其本身不為1,說明其本身是素數 { recheck: int p; if(a0!=1){p=a0;goto begin;} if(a1!=1){p=a1;;goto begin;} if(b0!=1){p=b0;goto begin;} if(b1!=1){p=b1;goto begin;} goto end; begin: ca0=ca1=cb0=cb1=0; get(a0,ca0,p);get(a1,ca1,p); get(b0,cb0,p);get(b1,cb1,p); if(ca0==ca1 && cb0==cb1 && ca0<=cb0) cnt=cb0-ca0+1; else if(ca0==ca1 && cb0<cb1 && ca0<=cb1) cnt=1; else if(ca0>ca1 && cb0==cb1 && ca1<=cb0) cnt=1; else if(ca0>ca1 && cb0<cb1 && ca1==cb1) cnt=1; else{ans=0;break;} ans*=cnt; goto recheck; } // printf("(%lld %lld %lld %lld)\n",a0,a1,b0,b1); end: printf("%d\n",ans); } return 0; }