Balls Rearrangement

Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 322    Accepted Submission(s): 114

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.

思路:我们可以发现循环节为a,b的最小公倍数tmp,所以我们只要求从1到tmp的花费即可,易知a和b的大小关系对题目答案没有影响,不妨设a>b,设从1到tmp的花费依次为 w1,w2,w3,....wtmp,我们可以将这tmp个值分成每b个一组,一共a/gcd组(gcd为a和b的最大公约数),我们设num[i]为第i组的和,现在的关键问题是num[i]怎么求,对于每一组num[i],这时第一个数在a盒子中的第po个,那么它的花费就是po-1(因为这个数一定是在b盒子的第一个),那么对于后面的第2个,第三个。。。。。。的花费也将是po-1,直到走到第po+b-1个,或者到第a个盒子(其实就是a和po+b-1去个小),若走到了第po+b-1个盒子,则这一组已经算完,为b*(po-1)花费,且po将被更新为po+b,否则,还应该计算剩下来的花费,这个和前一半类似,只不过这是a盒子从1开始,b盒子从a-po+2开始而已,这也是一串相同的花费,可以O(1)求出,然后更新po。将所有组求完后,剩下的工作就简单了。这里不再罗嗦。

以下是代码。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define ll long long
using namespace std;
ll dp[100010],sum[100010];
int Po[100010];
long long GCD(long long a,long long b)
{
if(b==0)
return a;
return GCD(b,a%b);
}
ll getans(ll x)
{
if(x>0)
return x;
return -x;
}
int main()
{
//freopen("dd.txt","r",stdin);
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
memset(dp,0,sizeof(dp));
memset(sum,0,sizeof(sum));
ll n,a,b;
cin>>n>>a>>b;
if(a<b)
swap(a,b);
if(a==b)
printf("0\n");
else
{
ll tmp=GCD(a,b);
ll tt=tmp;
tmp=a*b/tmp;
dp[1]=0;
sum[1]=0;
ll po=b+1;
Po[1]=1;
Po[2]=b+1;
for(int i=2;i<=a/tt;i++)
{
if(po+b-1<=a)
{
dp[i]=(po-1)*b;
po=po+b;
if(po>a)
po-=a;
}
else
{
dp[i]=(po-1)*(a-po+1);
int tt=a-po+2;
dp[i]+=(tt-1)*(b-tt+1);
po=b-tt+2;
if(po>a)
po-=a;
}
Po[i+1]=po;
sum[i]=sum[i-1]+dp[i];
} ll ans=0;
ans=sum[a/tt]*(n/tmp);
n%=tmp;
// cout<<n<<endl;
ll x=n/b;
ans+=sum[x];
n%=b;
if(n)
{
ll PO=Po[x+1];
for(int i=1;i<=n;i++)
{
ans+=getans(PO-i);
PO++;
if(PO>a)
PO-=a;
}
}
cout<<ans<<endl;
} }
return 0;
}

最新文章

  1. SE78、SWM0
  2. 记录一个bug -- sprintf
  3. oracle 执行执行动态存储过程名---其实就是存储过程名是个字符串参数
  4. 在oracle中通过链接服务器(dblink)访问sql server
  5. Mysql笔记——触发器简单实例
  6. Android编译提示ImportError: No module named bz2的解决办法
  7. RegExp子模式- &quot;()&quot;
  8. mysql主从同步错误解决和Slave_IO_Running: NO
  9. &lt;正向/反向&gt;最大匹配算法(Java)
  10. CSS 布局总结——固定宽度布局
  11. IOS某个ViewController禁止自动旋转
  12. 浅谈java垃圾回收机制
  13. /usr 的由来及/usr目录结
  14. 小强的HTML5移动开发之路(2)——HTML5的新特性
  15. Java 核心卷学习笔记(一)
  16. 【原】javascript笔记之this用法
  17. 爬虫时遇到的&#39; 编码错误gbk &#39; 的解决方案
  18. javascript 之 第七章第三节(this关键字)
  19. Oracle课程档案,第十五天
  20. EtherNet/IP 基本信息

热门文章

  1. WebView无法放大缩小解决方式
  2. PHP_零基础学php_3PHP函数、传参函数、默认参数、函数返回值
  3. 【视频】零基础学Android开发:蓝牙聊天室APP(二)
  4. javascript7
  5. APUE学习笔记(1):APUE运行环境
  6. SQL Server之记录筛选(top、ties、offset)汇总
  7. SQL Server的链接服务器(MySQL、Oracle、Ms_sql、Access、SYBASE)
  8. Android Intent 三解决
  9. solrnet的使用
  10. Scala是一门现代的多范式编程语言