hdu 4611 Balls Rearrangement

http://acm.hdu.edu.cn/showproblem.php?pid=4611

从A中向B中移动和从B中向A中移动的效果是一样的,我们假设从B中向A中移动 而且A>B

我们先求出所有在B[0]上的点移动到A上的分布情况 可以求出花费

当我们要求B[1]上的点移动到A上的分布情况时 相当于B[0]在A上的分布情况水平右移一个单位

由于B[1]点对于B[0]也向后移动了一个单位 所有相对位置没有移动

但是A中有一个地方需要改动 那就是每次A中最后一个位置的点需要移动到A[0]位置(因为对A进行取模的原因)

还有一个要注意的情况就是 B 在向后移动的时候 点的个数可能会减小 要特殊处理一下

代码:

#include<iostream>

#include<cstdio>

#include<string>

#include<cstring>

#include<cmath>

#include<set>

#include<map>

#include<stack>

#include<vector>

#include<algorithm>

#include<queue>

#include<bitset>

#include<deque>

#include<numeric>



//#pragma comment(linker, "/STACK:1024000000,1024000000")



using namespace std;



typedef long long ll;

typedef unsigned int uint;

typedef pair<int,int> pp;

const double eps=1e-9;

const int INF=0x3f3f3f3f;

const ll MOD=1000000007;

const int H=210000;

const int K=100001;

ll a[H];

int f(int x)

{

    return x+K;

}

ll readya(ll N,ll A,ll B)

{

    ll lcm=A*B/(__gcd(A,B));

    int n=lcm/B;

    int k=0;

    ll num=(N/B);

    if(N%B) ++num;

    for(int i=0;i<n;++i)

    {

        a[f(k)]+=num/n;

        k=(k+B)%A;

    }

    ll M=num%n;

    k=0;

    while(M--)

    {

        a[f(k)]++;

        k=(k+B)%A;

    }

    ll tmp=0;

    for(int i=1;i<A;++i)

    tmp+=a[f(i)]*i;

    return tmp;

}

int main()

{

    //freopen("data.in","r",stdin);

    int T;

    scanf("%d",&T);

    while(T--)

    {

        memset(a,0,sizeof(a));

        ll N,A,B;

        cin>>N>>A>>B;

        if(B>A) swap(A,B);

        if(A==B)

        {printf("0\n");continue;}

        ll L=0;

        ll R=readya(N,A,B);

        int num=N/B;

        if(N%B) ++num;

        ll ans=L+R;

        for(int i=1;i<B;++i)

        {

            a[f(-i)]=a[f(A-i)];

            R-=(a[f(A-i)]*(A-i));

            L+=(a[f(-i)]*i);

            a[f(A-i)]=0;

            int tmp=(N-i)/B;

            if((N-i)%B) ++tmp;

            if(tmp!=num)

            {

                int x=tmp*B+i;

                a[f(x%A-i)]--;

                if(x%A-i>0) {R-=abs(x%A-i);}

                if(x%A-i<0) {L-=abs(x%A-i);}

                num=tmp;

            }

            ans+=(L+R);

        }

        cout<<ans<<endl;

    }

    return 0;

}

 

 

你可能感兴趣的:(HDU)