Some day Bob buys B new boxes, and he wants to rearrange the balls from the old boxes to the new boxes. The new boxes are numbered from 0 to B-1. After the rearrangement, the ball numbered x should be in the box number b if x = b mod B.
This work may be very boring, so he wants to know the cost before the rearrangement. If he moves a ball from the old box numbered a to the new box numbered b, the cost he considered would be |a-b|. The total cost is the sum of the cost to move every ball, and it is what Bob is interested in now.
Then T test case followed. The only line of each test case are three integers N, A and B.(1<=N<=1000000000, 1<=A,B<=100000).
3 1000000000 1 1 8 2 4 11 5 3
0 8 16
题目大意:刚开始的时候bob有n个球和A个箱子,bob把球标号为0~n-1,标号为t的球放进第t%A个箱子里。现在bob又买了B个新箱子又用同样的方法吧标号为t的球放进第t%B个箱子里,每次把球从A箱子拿出来放进B箱子会有花费,为 |n%A-n%B| 求出移动所有的球的总的花费。
这个题明显能看得出来每隔LCM(A,B)为一个循环,所以刚开始想的是只需要求一个循环的花费乘循环次数最后再加上不足一个循环的花费就是结果,但是看了一下A和B的数据量,当A和B很大的时候可能n还没有LCM(A,B)大,所以如果只有这一个规律肯定是超时的。我们可以把一个循环的所有数写出来(就用实例的3和5就可以)。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18.....
A(3):0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0
B(5):0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3
差 0 0 0 3 3 2 1 1 1 4 1 1 2 2 2 0 0 0 3
我们可以看出当A,B都为0时就是一个循环,而且每两个零之间的差值都是相等的所以我们不必一个个数的加。只需算出每一段的第一个差值,然后乘上长度就可以。
代码还可以改进,但我懒得改了就先这样吧。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
ll GCD(ll a,ll b){
return b?GCD(b,a%b):a;
}
ll LCM(ll a,ll b){
return a*b/GCD(a,b);
}
int main()
{
ll n,A,B;
int T;
scanf("%d",&T);
while(T--){
scanf("%lld",&n);
scanf("%lld%lld",&A,&B);
ll aa=A,bb=B;
ll lcm=LCM(A,B);
ll t=0,ans=0;
if(n>=lcm){//求每一个LCM的差值的和
while(1){
if(aa+A<bb){
ans+=A*(ll)abs(aa%A-aa%B);
aa+=A;
}
else if(bb+B<aa){
ans+=B*(ll)abs(bb%A-bb%B);
bb+=B;
}
else if(aa>bb){
ans+=(aa-bb)*(ll)abs(bb%A-bb%B);
bb+=B;
}
else if(aa<bb){
ans+=(bb-aa)*(ll)abs(aa%A-aa%B);
aa+=A;
}
else
break;
}
t=n%lcm;
}
else{
t=n;
}
ans=ans*(n/lcm);
aa=A;bb=B;
while(t>min(aa,bb)){//求多余的部分差值的和
if(aa+A<bb){
if(aa+A>t){
ans+=(t-aa)*(ll)abs(aa%A-aa%B);
break;
}
ans+=A*(ll)abs(aa%A-aa%B);
aa+=A;
}
else if(bb+B<aa){
if(bb+B>t){
ans+=(t-bb)*(ll)abs(bb%A-bb%B);
break;
}
ans+=B*(ll)abs(bb%A-bb%B);
bb+=B;
}
else if(aa>bb){
if(aa>t){
ans+=(t-bb)*(ll)abs(bb%A-bb%B);
break;
}
ans+=(aa-bb)*(ll)abs(bb%A-bb%B);
bb+=B;
}
else if(aa<bb){
if(bb>t){
ans+=(t-aa)*(ll)abs(aa%A-aa%B);
break;
}
ans+=(bb-aa)*(ll)abs(aa%A-aa%B);
aa+=A;
}
else
break;
}
printf("%lld\n",ans);
}
return 0;
}