hdu 4611/4710 Balls Rearrangement 数论

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL __int64
LL gcd(LL a,LL b)
{
    return b==0?a:gcd(b,a%b);
}
LL lcm(LL a,LL b)
{
    return a*b/gcd(a,b);
}
LL find(LL a,LL b,LL c)
{
   // cout<<a<<" "<<b<<" "<<c<<endl;
    LL x=0,y=0,t,p=0,q;
    LL ans=0;
    while(p<c)
    {
        t=min(a-x,b-y);
        if(t+p>=c)
            t=c-p;
        ans+=t*abs((int)(y-x));
        x=(x+t)%a;
        y=(y+t)%b;
        p+=t;
    }
    return ans;
}
int main()
{
    LL n,a,b,T;
    cin>>T;
    while(T--)
    {
        cin>>n>>a>>b;
        LL p;
        p=lcm(a,b);
        cout<<(n/p)*find(a,b,p)+find(a,b,n%p)<<endl;
    }
    return 0;
}
/*
    p为a,b的最小公倍数,由题意可知。每p次,一个循环。
    列一个样例,如11 5 3,我们可以发现,
    5: 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 
    3:0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0
|a-b|:0 0 0 3 3 2 1 1 1 4 1 1 2 2 2 0  
    观察可知,当%a或者%b为0,到%a或者%b为0,这段中,|a-b|是相等的,这样就可以减小时间复杂度了。
*/

你可能感兴趣的:(数论)