Balls Rearrangement
Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1079 Accepted Submission(s): 416
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
多校第二场的第一题。
对给定的n,a,b,求对每一个i(1<=i<=n),(i%a-i%b)的绝对值的和。
如果直接暴力从1到n求解必然超时
但是我们很快就会发现,(i%a-i%b)的值是周期性出现的,周期为lcm(a,b)。
可对于很大并且互素的a,b来说,它们的最小公倍数可能非常大,导致这个周期可能只出现一次,这样的话就又和直接暴力没什么区别了。(比赛时就卡在这里...)
后来比赛后看了学姐的博客,发现到这依然可以进一步优化:
对于每一个周期的区间,我们又可以把它划分为多个子区间,在每个子区间内(i%a-i%b)的值是相等的,这样我们中要在一个周期的区间内扫描这样的子区间就可以了,复杂度为O(a+b),是可以接受的。
另外数据要用long long保存,不知道为什么,数据范围明明在long以内,可是交上去就是WA,还是后来一位学长给我改了过来
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #define LL long long 5 6 using namespace std; 7 8 LL gcd (LL x, LL y) 9 { 10 LL z; 11 if (x < y) 12 x ^= y ^= x ^= y; 13 while (y) 14 { 15 z = x % y; 16 x = y; 17 y = z; 18 } 19 return x; 20 } 21 22 LL lcm (LL x, LL y) 23 { 24 return x * y / gcd (x, y); 25 } 26 27 long long cal (LL n, LL a, LL b) 28 { 29 if (a == b) 30 return 0; 31 LL current = 0, atimes = 0, btimes = 0, t = lcm (a, b), times = n / t; 32 long long ans = 0; 33 if (times) 34 { 35 while (current < t) 36 { 37 if ( (atimes + 1) *a < (btimes + 1) *b) 38 { 39 atimes++; 40 ans += fabs (int (current % a - current % b)) * (atimes * a - current); 41 current = atimes * a; 42 } 43 else 44 { 45 btimes++; 46 ans += fabs (int (current % a - current % b)) * (btimes * b - current); 47 current = btimes * b; 48 } 49 } 50 ans *= times; 51 } 52 current = 0; 53 atimes = btimes = 0; 54 LL am, bm, e = n - t * times - 1; 55 while (current <= e) 56 { 57 am = (atimes + 1) * a; 58 bm = (btimes + 1) * b; 59 if (am < bm) 60 { 61 if (am <= e) 62 { 63 ans += fabs ( (int) current % a - current % b) * (am - current); 64 current = am; 65 atimes++; 66 } 67 else 68 { 69 ans += fabs (int (current % a - current % b)) * (e - current + 1); 70 break; 71 } 72 } 73 else 74 { 75 if (bm <= e) 76 { 77 ans += fabs (int (current % a - current % b)) * (bm - current); 78 current = bm; 79 btimes++; 80 } 81 else 82 { 83 ans += fabs (int (current % a - current % b)) * (e - current + 1); 84 break; 85 } 86 } 87 } 88 return ans; 89 } 90 91 int main() 92 { 93 int t; 94 LL n, a, b; 95 scanf ("%d", &t); 96 while (t--) 97 { 98 scanf ("%I64d %I64d %I64d", &n, &a, &b); 99 printf ("%I64d ", cal (n, a, b)); 100 } 101 return 0; 102 }