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;
}

 

 

posted on 2013-07-26 11:24  夜->  阅读(210)  评论(0编辑  收藏  举报