hdu 4611 Balls Rearrangement
比赛的时候没码出来,想太多了,总想对循环节找规律,最后还不是要对余数暴力查找。
两种排列方式,容易想到找最小公倍数,当然暴力也不是没有方法,模拟换行,因为已知当两种方式都没发生换行时,两者之差是不变的。然后离散一下就好了。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 using namespace std; 6 7 #define LL __int64 8 9 const int MAXN=1111111; 10 11 LL gcd(LL a,LL b) 12 { 13 if(!a)return b; 14 return gcd(b%a,a); 15 } 16 17 LL d[MAXN]; 18 19 int main() 20 { 21 int T,n,i; 22 LL a,b; 23 scanf("%d",&T); 24 while(T--) 25 { 26 scanf("%d%I64d%I64d",&n,&a,&b); 27 if(a>b) 28 swap(a,b); 29 LL c=a/gcd(a,b)*b; 30 LL x=n/c; 31 LL y=n%c; 32 LL t1=c/a; 33 LL t2=c/b; 34 LL nic1=1,nic2=1; 35 for(i=1;i<t1+t2;i++) 36 { 37 if(nic1*a<nic2*b){ 38 d[i]=nic1*a; 39 nic1++; 40 }else { 41 d[i]=nic2*b; 42 nic2++; 43 } 44 } 45 LL s=0,p=0;//p是不换行时移动的步数,规定向右为正,向左为负 46 d[0]=0; 47 for(i=1;i<t1+t2-1;i++) 48 { 49 if(d[i]%a==0){ 50 s+=abs((d[i+1]-d[i])*(p+a)); 51 p+=a; 52 }else { 53 s+=abs((d[i+1]-d[i])*(p-b)); 54 p-=b; 55 } 56 } 57 s*=x; 58 p=0; 59 if(y>d[1]) 60 for(i=1;i<t1+t2-1;i++) 61 { 62 if(y<=d[i+1]){ 63 if(d[i]%a==0){ 64 s+=abs((y-d[i])*(p+a)); 65 break; 66 }else { 67 s+=abs((y-d[i])*(p-b)); 68 break; 69 } 70 }else 71 if(d[i]%a==0){ 72 s+=abs((d[i+1]-d[i])*(p+a)); 73 p+=a; 74 }else { 75 s+=abs((d[i+1]-d[i])*(p-b)); 76 p-=b; 77 } 78 } 79 printf("%I64d\n",s); 80 } 81 return 0; 82 }