Neko does Maths CodeForces - 1152C 数论欧几里得
Neko does MathsCodeForces - 1152C
题目大意:给两个正整数a,b,找到一个非负整数k使得,a+k和b+k的最小公倍数最小,如果有多个k使得最小公倍数最小的话,输出最小的k。
首先让b>a,由lcm(a,b)=a*b/gcd(a,b),可以得出如果b%a==0,那么它们的最小公倍数就是b,此时的k就等于0。但如果b%a!=0的话,我们设g=gcd(a+k,b+k),那么就是有a+k=q1*g,b+k=q2*g,两者做差,那么b-a=(q2-q1)*g,由此我们可以知道g是b-a的因子。知道这个消息有什么用呢,我们可以在√(b-a) 内枚举g,这样g就是已知量了,我们设q3=(b-a)/g的话,q2=q1+q3,由lcm(a+k,b+k)=(a+k)*(b+k)/gcd(a+k,b+k),就有lcm(a+k,b+k)=q1*q2*g,那么lcm(a+k,b+k)=q1*(q1+q3)*g,只剩下一个未知量q1,而且要让lcm最小,q1也得最小,而q1=(a+k)/g,所以要让q1最小其实就是找一个最小的k使得(a+k)%g==0,那么k=(g-a%g)%g。这样的话枚举g,相应的k也就是出来了,再更新答案就好.
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 typedef long long ll; 5 int a,b,k; 6 ll ans; 7 ll lcm(ll a,ll b){ 8 return a*b/__gcd(a,b); 9 } 10 void solve(int g) 11 { 12 int nk=(g-a%g)%g; 13 ll nans=lcm(1ll*(a+nk),1ll*(b+nk)); 14 if(nans<ans||(nans==ans&&nk<k)) 15 k=nk,ans=nans; 16 } 17 int main() 18 { 19 scanf("%d%d",&a,&b); 20 if(a>b){ 21 ll t=a;a=b;b=t; 22 } 23 if(b%a==0) 24 { 25 printf("0\n"); 26 return 0;; 27 } 28 int dis=b-a; 29 k=0; 30 ans=lcm(a,b); 31 for(int i=1;i*i<=dis;i++) 32 { 33 if(dis%i==0) 34 { 35 solve(i); 36 solve(dis/i); 37 } 38 } 39 printf("%d\n",k); 40 return 0; 41 }
我太难了~给个三连吧,亲~~~