HDU 4611 Balls Rearrangement 解题报告

19 篇文章 0 订阅
18 篇文章 0 订阅

题目

2013 多校第二场 总结

题意:

有N个球,编号为0~n-1,一开始有A个箱子,编号0~A-1,将球x放到x%A那个箱子里。现在有B个新箱子,要把球x放到x%B那个箱子里,代价是|x%A-x%B|,求总代价。

题解:

N比较打所以不能暴力,可以这么想:

如果x`=x+LCM(A,B),那么|x%A-x%B|=|x`%A-x`%B|成立,且使得该等式成立的x和x`的最小差值也是LCM(A,B)。也就是在[0,LCM(A,B)]这个区间里,|x%A-x%B|遍历完所有可能的值。

连续的一段x中,当x%A和x%B没有发生跳变(从A-1变成0,B同理)时,|x%A-x%B|是相同的,即[0,LCM(A,B)]又可以分为一些小区间,每个小区间|x%A-x%B|是相同的。由于x%A只在x%A=A-1后跳变为0,所以总跳变数小于LCM(A,B)/A+LCM(A,B)/B,这样暴力找全部小区间是可以接受的,找到一个小区间后加上LCM(A,B)又是一个同样的区间。


//Time:109ms
//Memory:352KB
//Length:1065B
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#define MAXN 620
#define INF 10007
using namespace std;
int gcd(int a,int b)
{
    while(a%b!=0)
        a%=b,swap(a,b);
    return b;
}
int main()
{
    //freopen("/home/moor/Code/input","r",stdin);
    int ncase,n,a,b;
    long long lca,l,la,lb,tt,ans,tmp,step;
    scanf("%d",&ncase);
    while(ncase--)
    {
        ans=0;
        scanf("%d%d%d",&n,&a,&b);
        lca=(long long)a*b/gcd(a,b);
        l=0,la=a,lb=b;
        for(;l<n;)
        {
            tt=min(min(la,lb),(long long)n);
            tmp=abs(l%a-l%b);
            step=(n-l+lca-1)/lca;
            if((n-l)%lca<tt-l&&(n-l)%lca!=0)
                ans+=((n-l)%lca)*step*tmp+(tt-l-(n-l)%lca)*(step-1)*tmp;
            else    ans+=tmp*(tt-l)*step;
            l=tt;
            if(la==lb)  break;
            if(l==la)   la+=a;
            else    lb+=b;
        }
        cout<<ans<<'\n';
    }
    return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值