题意描述:有1-n编号的物品,放在0到a-1的盒子中,其中第i个物品放在 i%a 编号的盒子中,而现在要搬动物品,把这些物品放在0到b-1的盒子中,其中i物品放在i%b盒子中,每件物品移动的量为abs(ida-idb) ida,idb分别代表物品i在a,b盒子的编号,求总的移动量。
易知循环节是LCM(a,b),但是这个循环节太大了,如果暴力更新必须超时,考虑到成段改变,因为每一段的长度len与一个步长mi的乘积就是这段物品移动的总量,注意可能出现填充不满的情况。
还有因为没有MOD所以用int64,abs超恶心,在同时加入iostream和cstdio头文件时候会有二义性,而自己又定义一个果断CE。
#include<cstdio>
using namespace std;
#define ll __int64
ll a,b;
ll abs(ll k){
return k>0?k:-k;
}
ll gcd(ll a,ll b){
if(!b) return a;
return gcd(b,a%b);
}
ll count(ll n){
ll t,i,ret,mi;
i=0;
ret=0;
while(i<n){
t=((a-i%a)>(b-i%b))?(b-i%b):(a-i%a);
if(i+t>n) t=n-i;
ret+=abs(i%a-i%b)*t;
i+=t;
}
return ret;
}
int main(){
ll t,i,j,n,lcm;
scanf("%I64d",&t);
while(t--){
scanf("%I64d %I64d %I64d",&n,&a,&b);
lcm=a/gcd(a,b)*b;
ll ret=0;
if(lcm>n) ret=count(n);
else ret=n/lcm*count(lcm)+count(n%lcm);
printf("%I64d\n",ret);
}
return 0;
}