这个题感觉真是非常考验代码能力啊!
做了好长时间才做出来。 思路还是可以慢慢想出来的。
最上来 。 这个题明显是个周期题。 那么找周期就很好找了。 肯定两个箱子的最小公倍数。
但是当数非常大的时候。 比如 a b 都是 99999 99998 这种的时候。 最小公倍数很大。 如果在一个周期内 求值 如果每个箱子枚举的话。
那就明显的太慢。 方法就是 一段一段的求。 我们对 11 3 5 这组样例 写出他的过程。 我们就会发现。 很多地方 相邻的几个球 的在 a箱子 和 b箱子的 差值 是相同的。
利用这个特点。我们就可以顺利解决这个问题了。 注意都是用long long
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define maxn 100+10
#define INF 1<<30
ll gcd(ll a, ll b){
return b == 0? a:gcd(b,a%b);
}
ll on(ll a, ll b, ll t){
ll sum = 0;
if(a == b)
return 0;
for(int i = 0; i < t;){
int m = min(a-i%a,b-i%b);
if(i + m >= t+1){
m = t-i;
i = t;
}
// printf("-----------\n");
// printf("%d %d\n",i,m);
sum += m*abs(i%b-i%a);
// printf("%I64d\n",sum);
i += m;
}
return sum;
}
int main (){
int t;
scanf("%d",&t);
while(t--){
ll n,a,b;
ll le = 0;
ll sum = 0;
scanf("%I64d%I64d%I64d",&n,&a,&b);
ll m = a*b/gcd(a,b);
if(n >= m){
int k = n/m;
sum += k*on(a,b,m);
le = n - k*m;
}
else
le = n;
sum += on(a,b,le);
printf("%I64d\n",sum);
}
return 0;
}