HPU 1046: QAQ的数学问题 【贝祖定理】

1046: QAQ的数学问题 [数学]

时间限制: 1 Sec   内存限制: 128 MB
提交: 61   解决: 11
[ 提交][ 状态][ 讨论版]

题目描述

QAQ很喜欢数学,尤其对 LCM LCM(最小公倍数)很感兴趣。
对于数对 (6,10) (6,10),可以得出 LCM(6,10)=30 LCM(6,10)=30。为了让 LCM LCM的值最小化,他尝试把 6 6 10 10全部加上 2 2,这样得到 LCM(8,12)=24<30 LCM(8,12)=24<30
经过无数次的尝试,QAQ发现总是可以通过上面相加的方式(必须加的是非负整数)让 LCM LCM的值达到最小的,但是他忘记至少需要加多少了,所以你来请帮帮他吧。

输入

第一行输入一个整数 T T,代表有 T T组测试数据。

每组数据输入两个整数 A,B A,B,分别代表上面提到信息。


注: 1<=T<=20001<=AB<=2000000000 1<=T<=2000,1<=A,B<=2000000000

输出

对每组数据,输出一个结果,代表QAQ至少需要加的数。

样例输入

3
6 10
4 10
3 10

样例输出

2
2
4

来源

CZY


题解:

因为A和B的差始终是不变的,那么考虑差对结果的影响。

发现不管怎么变,GCD(A,B)就是abs(A−B)的一个因子。

我们预处理因子,然后枚举因子维护最优解即可。

时间复杂度O(T∗log(abs(A−B)))。


AC代码:

#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;

typedef long long LL;

int f[10111];

LL GCD(LL a,LL b) {
	return !b?a:GCD(b,a%b);
}
LL LCM(LL a,LL b) {
	return a/GCD(a,b)*b;
}

int main() {
	LL T; scanf("%lld",&T);
	while(T--) {
		LL a,b; scanf("%lld%lld",&a,&b);
		if(a<b) swap(a,b);
		LL m=a-b,i,cnt=0;
		for( i=1;i*i<m;++i) {
			if(m%i==0) {
				f[cnt++]=i; f[cnt++]=m/i; 
			}
		}
		if(m%i==0) f[cnt++]=i;
		LL ans=LCM(a,b),x=0;
	    for(i=0;i<cnt;++i) {
	    	LL j=f[i]-b%f[i];//求b对于f[i]的逆 不要用while去找 会T 
			LL tem=(a+j)/f[i]*(b+j);
			if(tem<ans) {
				ans=tem; x=j;
			}
		} 
		printf("%lld\n",x);
	}
 	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值