题目:https://www.luogu.org/problemnew/show/P1072
满足条件的数 x 一定是 a1 的倍数,b1 的因数,a0/a1 与 x/a1 互质,b1/b0 与 b1/x 互质;
按质因子来看,满足要求的数 x 的某个质因子 pi 的次数应该:
1.大于等于 a1 的,小于等于 b1 的;
2.如果 a0/a1 有 pi 剩余,则 x 的 pi 的次数只能是 a1 的 pi 的次数(无选择余地,不贡献答案);
3.如果 b1/b0 有 pi 剩余,则 x 的 pi 的次数只能是 b1 的 pi 的次数(同上);
然后要注意条件2,3之间可能有冲突,判掉即可。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> using namespace std; typedef long long ll; int const xn=405; int n,cnt,p[xn],k[5][xn]; map<int,int>mp; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();} while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return f?ret:-ret; } void solve(int x,int l) { for(int i=2;i*i<=x;i++) { if(x%i)continue; if(!mp[i])mp[i]=++cnt,p[cnt]=i; int t=mp[i]; while(x%i==0)k[l][t]++,x/=i; } if(x==1)return; if(!mp[x])mp[x]=++cnt,p[cnt]=x; k[l][mp[x]]=1; } int main() { n=rd(); while(n--) { ll ans=1; bool fl=0; memset(k,0,sizeof k); cnt=0; mp.clear(); for(int i=0,x;i<4;i++)x=rd(),solve(x,i); // printf("cnt=%d\n",cnt); // for(int i=1;i<=cnt;i++) // { // printf("p[%d]=%d:",i,p[i]); // for(int j=0;j<4;j++)printf("k[%d]=%d ",j,k[j][i]); // printf("\n"); // } for(int i=1;i<=cnt;i++) { if(k[1][i]>k[3][i]||k[0][i]<k[1][i]||k[3][i]<k[2][i]){fl=1; break;} if(k[3][i]!=k[2][i]&&k[0][i]!=k[1][i]&&k[3][i]!=k[1][i]) {fl=1; break;}//必须有 lcm--i -><-必须有 gcd--i //!!! if(k[0][i]!=k[1][i]||k[2][i]!=k[3][i])continue;//则 i 处无选择余地 ans=ans*(k[3][i]-k[1][i]+1); } if(fl)printf("0\n"); else printf("%lld\n",ans); } return 0; }