HDU 4710 Balls Rearrangement
这道题太搞笑了,估计是HDU的测试数据太弱了,我直接暴力加一点小技巧都过了,sigh。。。
不过有一点值得注意的是,64位数据最好用cin/cout,否则可能会产生输入和输出错误。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4710
好吧,就是求a,b 的最小公倍数Q,然后如果Q>n,就直接进行上限为Q的模拟,当然,要加一点小技巧。
技巧:设现在要往A,B箱子里放球,箱子编号分别为la,lb,那么剩余量就是A-la,和B-lb。用剩余量最小的那个直接进行加法操作,相见代码。。。
貌似这个技巧叫做跳跃求值,我不知道。。。
如果Q<n,就进行上限为Q的模拟,模拟n/Q次,再模拟一次,上限为n%Q。
总量就是n/Q*calcu(Q,a,b) + calcu(n%Q,a,b) .
上代码:
1 #include<stdio.h> 2 #include<iostream> 3 using namespace std; 4 #include<math.h> 5 #include<string> 6 #include<map> 7 #include<queue> 8 #include<stdlib.h> 9 #include<algorithm> 10 11 #define repA(p,q,i) for( int (i)=(p); (i)!=(q); ++(i) ) 12 #define repAE(p,q,i) for( int (i)=(p); (i)<=(q); ++(i) ) 13 #define repD(p,q,i) for( int (i)=(p); (i)!=(q); --(i) ) 14 #define repDE(p,q,i) for( int (i)=(p); (i)>=(q); --(i) ) 15 #define ll long long 16 17 ll gcd(ll a, ll b); 18 ll calcu( ll round, ll ca, ll cb ); 19 20 int main() 21 { 22 ll a,b,n; 23 int test; scanf("%d",&test); 24 while(test--) 25 { 26 cin>>n>>a>>b ; 27 ll GCD = gcd(a, b) ; 28 ll circle = a*b/GCD ; 29 if(a == b) 30 { 31 printf("0\n"); 32 continue; 33 } 34 35 if( circle > n ) 36 { 37 cout<< calcu(n,a,b) << endl ; 38 continue; 39 } 40 ll ans = n/circle * calcu(circle,a,b); 41 42 ans += calcu(n%circle,a,b); 43 cout<<ans<<endl; 44 45 } 46 return 0; 47 } 48 49 ll gcd(ll a, ll b) 50 { return b==0?a:gcd(b,a%b); } 51 52 53 ll calcu( ll round, ll ca, ll cb ) 54 { 55 ll la=0, lb=0, gone, ans=0; 56 int i=0; 57 while( i < round ) 58 { 59 gone = min( ca-la , cb-lb ) ; 60 if( i+gone < round ) 61 { 62 i += gone; 63 ans += gone * abs(la-lb) ; 64 la = (la+gone) % ca ; 65 lb = (lb+gone) % cb ; 66 } 67 else 68 { 69 ans += (round-i) * abs(la-lb) ; 70 break; 71 } 72 } 73 return ans ; 74 }
当然我以为我的代码应该是野鸡代码,水过去的,不过后来搜了下题解,发现别人的好像跟我差不多思路,代码还没有我简洁。。。。
当然,简洁换来的是速度的下降,本质没什么区别。
贴一下吧,摘自:http://www.cnblogs.com/kuangbin/p/3214791.html
1 #include <stdio.h> 2 #include <algorithm> 3 #include <iostream> 4 #include <string.h> 5 #include <set> 6 #include <map> 7 #include <vector> 8 #include <queue> 9 #include <string> 10 #include <math.h> 11 using namespace std; 12 long long gcd(long long a,long long b) 13 { 14 if(b==0)return a; 15 else return gcd(b,a%b); 16 } 17 long long lcm(long long a,long long b) 18 { 19 return a/gcd(a,b)*b; 20 } 21 long long calc(int n,int a,int b) 22 { 23 long long ans = 0; 24 int i = 0; 25 int ta=0,tb=0; 26 int p = 0; 27 while(i < n) 28 { 29 if(ta+a >= n && tb+b >= n) 30 { 31 ans += (long long)(n-i)*p; 32 i = n; 33 continue; 34 } 35 if(ta+a < tb+b) 36 { 37 ans += (long long)p*(ta+a-i); 38 i = ta+a; 39 p = i - tb; 40 ta+=a; 41 } 42 else if(ta+a==tb+b) 43 { 44 ans+= (long long)p*(ta+a-i); 45 i = ta+a; 46 ta+=a; 47 tb+=b; 48 p = 0; 49 } 50 else 51 { 52 ans += (long long)p*(tb+b-i); 53 i = tb+b; 54 tb+= b; 55 p = i-ta; 56 } 57 } 58 return ans; 59 } 60 int main() 61 { 62 //freopen("in.txt","r",stdin); 63 //freopen("out.txt","w",stdout); 64 int T; 65 int n,a,b; 66 scanf("%d",&T); 67 while(T--) 68 { 69 scanf("%d%d%d",&n,&a,&b); 70 if(a==b) 71 { 72 printf("0\n"); 73 continue; 74 } 75 if(a < b)swap(a,b); 76 long long LCM = lcm(a,b); 77 if(LCM >= n) 78 { 79 printf("%I64d\n",calc(n,a,b)); 80 continue; 81 } 82 long long tmp = calc(LCM,a,b); 83 long long ans = tmp * (n/LCM)+calc(n%LCM,a,b); 84 printf("%I64d\n",ans); 85 } 86 return 0; 87 }
To Be The Best Of Yourself