您的位置:首页 > 其它

HDU 4611 Balls Rearrangement

2013-09-12 16:04 281 查看
这道题第一眼看上去就知道是数论的题  可惜做的题少了  不知道怎么下手   自己推了很久的公式也没退出来    后来看了别人的解题报告发现是最小公倍数的问题    再加上一个模拟就解决了    

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;

LL gcd(LL a, LL b)
{
return b==0? a:gcd(b,a%b);
}

LL Solve(LL n,LL a,LL b)//这段程序的作用就是模拟移动的过程 因为直接一个个的移会超时  所以把移动步长相等的一次移动就不会超时了
{
LL now=0,ret=0,tmp,x=0,y=0;
while( now < n )
{
tmp=min(a-x,b-y);//有多少个移动步长是相等的  也就是连续的移动的那几个|a-b|相等
if (now+tmp>n) tmp = n - now;
ret += tmp*abs(x-y);
x = (x+tmp)%a;   //计算下次移动的步长
y = (y+tmp)%b;
now += tmp;//向后移
}
return ret;
}

int main()
{
int T;
scanf("%d",&T);
while(T--)
{
LL N,A,B;
scanf("%I64d%I64d%I64d",&N,&A,&B);
LL sum;
LL lcm = A / gcd(A,B)*B;
if(lcm >= N)
sum = Solve(N,A,B);
else sum = Solve(lcm,A,B)*(N/lcm) + Solve(N%lcm,A,B);
printf("%I64d\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数论 模拟