hdu 4611 Balls Rearrangement 数学

本文针对一个具体的编程问题——球重组问题进行了解析。该问题是关于如何计算将一定数量的球从一组箱子重新分配到另一组箱子的成本。文章通过数学方法找到解决此问题的有效途径,并提供了一段完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Balls Rearrangement

Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)


Problem Description
  Bob has N balls and A boxes. He numbers the balls from 0 to N-1, and numbers the boxes from 0 to A-1. To find the balls easily, he puts the ball numbered x into the box numbered a if x = a mod A.   Some day Bob buys B new boxes, and he wants to rearrange the balls from the old boxes to the new boxes. The new boxes are numbered from 0 to B-1. After the rearrangement, the ball numbered x should be in the box number b if x = b mod B.
  This work may be very boring, so he wants to know the cost before the rearrangement. If he moves a ball from the old box numbered a to the new box numbered b, the cost he considered would be |a-b|. The total cost is the sum of the cost to move every ball, and it is what Bob is interested in now.
 

 

Input
  The first line of the input is an integer T, the number of test cases.(0<T<=50) 
  Then T test case followed. The only line of each test case are three integers N, A and B.(1<=N<=1000000000, 1<=A,B<=100000).
 

 

Output
  For each test case, output the total cost.
 

 

Sample Input
3 1000000000 1 1 8 2 4 11 5 3
 

 

Sample Output
0 8 16
 

 

Author
SYSU
 

 

Source
题意:求sigma(i%a-i%b);   
思路:显然lcm为循环节;
     当同时模加1 的时候差值相等所以只有在对A或B取模为0的时候会改变;
   即A、B的倍数为断点;
#include<bits/stdc++.h>
using namespace std;
#define ll __int64
#define esp 0.00000000001
const int N=3e5+10,M=1e6+10,inf=1e9,mod=1e9+7;
ll a[N],b[N],c[N];
ll gcd(ll x,ll y)
{
    return y==0?x:gcd(y,x%y);
}
int main()
{
    ll x,y,z,i,t;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%I64d%I64d%I64d",&x,&y,&z);
        ll gc=gcd(y,z);
        ll lcm=y*z/gc;
        int ji=1;
        for(i=1;i<=lcm/y;i++)
        a[ji++]=i*y;
        for(i=1;i<lcm/z;i++)
        a[ji++]=i*z;
        sort(a,a+ji);
        for(i=0;i<ji-1;i++)
        {
            b[i]=a[i+1]-a[i];
            c[i]=abs(a[i]%y-a[i]%z);
        }
        ll sum=0;
        for(i=0;i<ji-1;i++)
        sum+=b[i]*c[i];
        ll ans=0;
        ans+=x/lcm*sum;
        x%=lcm;
        for(i=0;i<ji-1;i++)
        {
            if(x<=0)
            break;
            if(x<b[i])
            ans+=x*c[i];
            else
            ans+=b[i]*c[i];
            x-=b[i];
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/jhz033/p/5658093.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值