【问题描述】
Hanks博士是BT(Bio-Tech,生物技术)领域的知名专家,他的儿子名叫Hankson。现在,刚刚放学回家的Hankson正在思考一个有趣的问题。
今天在课堂上,老师讲解了如何求两个正整数c1和c2的最大公约数和最小公倍数。现在Hankson认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1,设某未知正整数x满足:
1、 x和a0的最大公约数是a1;
2、 x和b0的最小公倍数是b1。
Hankson的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的x并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x的个数。请你帮助他编程求解这个问题。
【输入】
输入文件名为son.in。第一行为一个正整数n,表示有n组输入数据。接下来的n行每行一组输入数据,为四个正整数a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入数据保证a0能被a1整除,b1能被b0整除。
【输出】
输出文件son.out共n行。每组输入数据的输出结果占一行,为一个整数。
对于每组数据:若不存在这样的x,请输出0;
若存在这样的x,请输出满足条件的x的个数;
【输出输出样例】
son.in
2
41 1 96 288
95 1 37 1776
son.out
6
2
【说明】
第一组输入数据,x可以是9、18、36、72、144、288,共有6个。
第二组输入数据,x可以是48、1776,共有2个。
【数据范围】
对于50%的数据,保证有1≤a0,b1,b0,b1≤10000且n≤100。
对于100%的数据,保证有1≤a0,b1,b0,b1≤2,000,000,000且n≤2000。
分析:
根据最小公倍数和最大公约数分解质因数指数的特殊关系进行优化
比如两个数,分解质因数可以得到以下的式子
A=p1^a1+p2^a2+p3^a3……
B=p1^b1+p2^b2+p3^a3……
例如6和21就可以分解成
6=2^1+3^1+5^0+7^0……
21=2^0+3^1+5^0+7^1……
最大公约数=2^(min(a1,b1))+3^(min(a2,b2))+5^(min(a3,b3))+7^(min(a4,b4))…
最小公倍数=2^(max(a1,b1))+3^(max(a2,b2))+5^(max(a3,b3))+7^(max(a4,b4))…
我们可以先预处理50000以内的质数,
然后每读入一组数据,初始答案ans=1,
然后我们循环质数,看a0、a1、b0、b1里面有多少个该质数因子,
我们设求出来的该因子个数分别是t1、t2、t3、t4
如果数据合法,那么t1>=t2,t3<=t4
根据最大公约数和最小公倍数的定义,
我们要求的数所拥有的该质因子个数s必须要同时满足以下限制条件:
若t1>t2,则s=t2
若t1=t2,则s>=t2 //t2是t1和s取min的结果
若t3 < t4,则s=t4
若t3=t4,则s<=t4 //t4是t3和s取max的结果
若t1 < t2||t3>t4—->无解
让我们来看一下判断:
if (t1>t2) f1=1; mn=t2; if (t3<t4) f2=1; mx=t4; if (!(f1||f2)) ans=ans*(mx-mn+1); else if (f1==0&&f2==0&&mx!=mn) { printf("0\n");return; }
如果t1>t2 说明s只能等于t2,f1=1
如果t3 < t4 说明s只能等于t3,f2=1
如果规定只能等于一个值,而(f1=1,f2=1),且mn!=mx,ans=0
只要有一个规定值了,ans*=1
然而
luogu上第二个点过不去。。。
这里写代码片 #include<cstdio> #include<cstring> #include<iostream> #include<cmath> #define ll long long using namespace std; const int N=500000; const int INF=0x33333333; ll sshu[50010],tot=0; bool no[500010]; ll a0,a1,b0,b1; int t1,t2,t3,t4,n; void cl() { memset(no,0,sizeof(no)); for (ll i=2;i<=N;i++) { if (!no[i]) sshu[++tot]=i; for (int j=1;sshu[j]*i<=N&&j<=tot;j++) { no[i*sshu[j]]=1; if (i%sshu[j]==0) break; } } } void doit() { ll ans=1; int i,j,mx=0,mn=INF; bool f1,f2; for (i=1;i<=tot;i++) //对于每个因子都要这样处理 { t1=t2=t3=t4=0; f1=0,f2=0; mn=mx=-1; while(a0>1&&a0%sshu[i]==0) t1++,a0=a0/sshu[i]; while(a1>1&&a1%sshu[i]==0) t2++,a1=a1/sshu[i]; while(b0>1&&b0%sshu[i]==0) t3++,b0=b0/sshu[i]; while(b1>0&&b1%sshu[i]==0) t4++,b1=b1/sshu[i]; if (t1<t2||t3>t4) { printf("0\n"); return; } if (t1>t2) f1=1; mn=t2; if (t3<t4) f2=1; mx=t4; if (!(f1||f2)) ans=ans*(mx-mn+1); else if (f1&&f2&&mx!=mn) { printf("0\n"); return; } } printf("%lld\n",ans); } int main() { cl(); scanf("%d",&n); while (n--) { scanf("%lld%lld%lld%lld",&a0,&a1,&b0,&b1); doit(); } return 0; }
来源:https://www.cnblogs.com/wutongtong3117/p/7673446.html