hdu 4611 Balls Rearrangement (13多校#2-A)

来源:互联网 发布:苏尚卿 知乎 编辑:程序博客网 时间:2024/06/06 04:03

题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=4611

题解:显然一个个求和时会以lcm(a,b)为周期,但是一旦a,b公因子比较少,这样也还是会超时的, i++这个跨度太小.  注意到如果mod a的序列在上升,mod b的序列也在上升,则ans+= 的那个值是不变的,这样我们就可以增加跨度了。  考虑从i开始的跨度为jump的序列时,只需要去 a-i%a ,b-i%b的较小值就可以了。 最后注意一下i+jump不可以超过边界,一旦超过,我们把i赋值成很大,这样保证会退出去就可以了


#include<iostream>#include<cmath>using namespace std;typedef long long inta;inta min(inta a,inta b){   if(a>b) return b;   else return a;}inta gcd(inta a,inta b){   if(b==0)  return a;   else return gcd(b,a%b);}inta lcm(inta a,inta b){  return a/gcd(a,b)*b;}inta cost(inta a,inta b,inta n)     {   inta ans=0;   for(int i=0;i<n;)    {      inta jump=min(a-i%a,b-i%b);      //  边界处理      if(i+jump>=n+1)      {          jump=n-i;          i=n;      }      ans+=(jump)*fabs(i%a-i%b);      //last=i;      i+=jump;    }   return ans;}int main(){   int T;   cin>>T;   while(T--)   {     inta n,a,b;     cin>>n>>a>>b;     inta ans=0;     inta q=0;     if(n>=lcm(a,b))     {       q=n/lcm(a,b);       ans=q*cost(a,b,lcm(a,b));     }     ans+=cost(a,b,n-q*lcm(a,b));     cout<<ans<<endl;   }}