Fraction Construction Problem
3
4 1
1 6
37 111
-1 -1 -1 -1
1 2 1 3
145 87 104 78
对于整式
给定a,b的值,求任意一组c,d,e,f的值使得等式成立。
无解则输出-1-1-1-1。
首先看这个式子,在d*f==b时可以化成这样,一拍脑瓜想到可以用扩欧解方程。
所以我们只要把b分解成d*f,并且满足gcd(d,f)=1,这样就可以使构造成立(通分的知识,学前班的),然后一套模板解方程。于是我们凑出了一组答案。
有的童鞋想,那那那我d和f其中一个为1不就可以了。
嗯没错,可是题目中说了,d和f均小于b(不然不是水题了?),所以我们需要找出b的两个互质因子。
但是如果a和b不是互质的,那就一约分后d或f就可以取1了。所以这种情况可以直接特判掉,即方便又省时(非常的nice)。
但是也有可能他找不到一对互质因子,那就是无解了。比如b=81,它不能分解成互质因子。除此以外,b=1或b是质数当然也是无解的情况。
(无解判断方式有很多,自行选择)
1、gcd(a,b)!=1,直接使d(或f)=0,出答案,简洁明了。
2、gcd(a,b)=1&&(prime(b)||b无法拆成互质数之积||b=1),则无解,畅快淋漓,速战速决。
3、其他有解情况,则用扩欧解方程,然后通过解的正负判断对应。
#include
#define ll long long
using namespace std;
const int MAXN=2e6+10;
int gcd(int a,int b){return a%b==0?b:gcd(b,a%b);}//听+说ll会TLE,果然。
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){x=1;y=0;return a;}
ll c=exgcd(b,a%b,y,x);
y-=a/b*x;return c;
}//扩欧
int main()
{
int t,a,b,r;
for(scanf("%d",&t);t--;){//学习dalao的新操作
scanf("%d%d",&a,&b);
if(b==1){puts("-1 -1 -1 -1");continue;}//b是1不要再继续了,省时。
r=gcd(a,b);
if(r!=1){
printf("%d %d %d %d\n",a/r+b/r,b/r,b/r,b/r);
continue;
}//ab不互质直接出答案
ll x,y;
int d=1,f=b;
for(d=2;d*d<=b;d++)
if(b%d==0&&gcd(d,b/d)==1){
d*=1ll,f=1ll*b/d;break;
}//穷举法求素因子,也可以用类筛法。
if(f==b){puts("-1 -1 -1 -1");continue;}//找不到合法的分解,素数也包含在内。
r=exgcd(f,d,x,y);//解方程
x=x*1ll*a;y=y*1ll*a;//扩欧基本操作--求通解
if(x>0&&y<0)
printf("%lld %d %lld %d\n",x,d,-y,f);
else
printf("%lld %d %lld %d\n",y,f,-x,d);
//根据正负判断对应
}
}
有错即评。