hdu4710Balls Rearrangement

Balls Rearrangement

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 247    Accepted Submission(s): 124


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
 

Source
 

Recommend
liuyiding
 

老实说我做这道题时,想到了a跟b的最小公倍数是他们的周期。。。
只要遍历一次周期就行了、、
不过后来想了一下还是不行。。。
因为a跟b的最小公倍数可以是100000*99999 。。。
这绝对会超时的,后来没有想出什么有效的方法就放下来了。。。
后来这网上找到一位高手的题解才知道我只想出了一半,还有一半是查找他们的公共部分。。
因为公共部分的差值是相同的orz。
还要注意是数据很大要用64位来存。。
#include <cstdio>  
#include <cstring>  
#include <algorithm>  
#include <iostream>  
#include<cmath>
using namespace std;  
__int64 Abs(__int64 a,__int64 b)
{
	return a>b?(a-b):(b-a);
}
__int64 max(__int64 a,__int64 b)
{
	if(a>b)return a;
	else return b;
}
__int64 min(__int64 a,__int64 b)
{
	if(a>b)return b;
	else return a;
}

__int64 work(__int64 n,__int64 a,__int64 b)
{
	__int64 now = 0,tmp,sum=0,x=0,y=0;//x和y是A箱序列和B箱序列结束部分的位置

	while(now < n)
	{
		tmp = min(a-x,b-y);
		if(tmp+now > n)
			tmp = n-now;
			sum+=tmp*Abs(x,y);
			now+= tmp;
			x = (tmp+x)%a;
			y = (tmp+y)%b;

	}
	return sum;
}

__int64 LCM(__int64 a, __int64 b)//最小公倍数 
{  
    __int64 aa = max(a, b);  
    __int64 bb = min(a, b);  
    do {  
        __int64 r = aa % bb;  
        aa = bb;  
        bb = r;  
    }while(bb);  
    return a * b / aa;  
}  



int main()
{
	 __int64 num;
	__int64 n,a,b,G,k,k1;
	__int64 sum;
	scanf("%I64d",&num);
	while(num--)
	{
		sum=0;
		scanf("%I64d%I64d%I64d",&n,&a,&b);
		G=LCM(a,b);

		if(G>=n)
		{		
			printf("%I64d\n",work(n,a,b));
		}
		
		else 
		{
			k=n/G;
		    k1=n%G;
			
				printf("%I64d\n",k*work(G,a,b)+work(k1,a,b));
		}
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值