【NOIP2016提高A組模擬8.15】Throw
阿新 • • 發佈:2018-05-16
tin sca begin spa 元組 int clu AI pac
但這顯然會超時。
我們用二元組(l,r)來代表每一個狀態,l=b-a,r=c-b。(顯然根節點就是l=r的二元組)
當這個狀態向父親跳時,就變成
\[\left\{\begin{array}\\l>r,(l,r)-->(l-r,r) \\l<r,(l,r)-->(l,r-l) \end{array}\right.\]
發現這樣轉移就類似於輾轉相除法!
用倍增求lca就可以了。
題目
分析
首先對於一個狀態(a,b,c),假定a<=b<=c;
現在考慮一下這個狀態,的轉移方案:
\[1,中間向兩邊跳(a,b,c)-->(a*2-b,a,c)、(a,b,c)-->(a,c,2*c-b)\]
\[2、兩邊向中間跳\left\{\begin{array}\\b-a>c-b,(a,b,c)-->(a,2*b-c,b) \\b-a<c-b,(a,b,c)-->(b,2*b-a,c) \end{array}\right.\]
我們將一個狀態兩邊向中間轉移後的狀態設為這個狀態的父親,我們發現,這剛好形成了一顆樹。
那麽從起點和終點都分別向父親跳,用hash判重,如果有交點就輸出yes以及ans,反之。
我們用二元組(l,r)來代表每一個狀態,l=b-a,r=c-b。(顯然根節點就是l=r的二元組)
當這個狀態向父親跳時,就變成
\[\left\{\begin{array}\\l>r,(l,r)-->(l-r,r) \\l<r,(l,r)-->(l,r-l) \end{array}\right.\]
發現這樣轉移就類似於輾轉相除法!
用倍增求lca就可以了。
#include <cmath> #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> const long long maxlongint=2147483647; const long long mo=10000007; const long long N=50005; using namespace std; long long b[4],n=3,m,t[4],a[4],mi[35],deep,deep1,a1[4],b1[4],f[2][2],dd,l,r,ll,rr,ans; bool q; long long do1(long long x) { long long k=0,p; while(x>0) { sort(a+1,a+3+1); k=0; if(l==r) { q=false; break; } if(l>r) { if(l%r==0) k--; k+=l/r; p=r; if(x-k>=0) { l-=k*r; x-=k; a[3]-=(k-k/2)*p*2; a[2]-=(k/2)*p*2; } else { l-=x*r; k=x; a[3]-=(k-k/2)*p*2; a[2]-=(k/2)*p*2; break; } } else { if(r%l==0) k--; k+=r/l; p=l; if(x-k>=0) { r-=k*l; x-=k; a[1]+=(k-k/2)*p*2; a[2]+=(k/2)*p*2; } else { r-=x*l; k=x; a[1]+=(k-k/2)*p*2; a[2]+=(k/2)*p*2; break; } } } } long long do2(long long x) { long long k=0,p; while(x>0) { sort(b+1,b+3+1); k=0; if(ll==rr) { q=false; break; } if(ll>rr) { if(ll%rr==0) k--; k+=ll/rr; p=rr; if(x-k>=0) { ll-=k*rr; x-=k; b[3]-=(k-k/2)*p*2; b[2]-=(k/2)*p*2; } else { ll-=x*rr; k=x; b[3]-=(k-k/2)*p*2; b[2]-=(k/2)*p*2; break; } } else { if(rr%ll==0) k--; k+=rr/ll; p=ll; if(x-k>=0) { rr-=k*ll; x-=k; b[1]+=(k-k/2)*p*2; b[2]+=(k/2)*p*2; } else { rr-=x*ll; k=x; b[1]+=(k-k/2)*p*2; b[2]+=(k/2)*p*2; break; } } } } int main() { for(long long i=1;i<=n;i++) scanf("%lld",&a[i]); for(long long i=1;i<=n;i++) scanf("%lld",&b[i]); mi[0]=1; for(long long i=1;i<=33;i++) mi[i]=mi[i-1]*2; sort(a+1,a+3+1); sort(b+1,b+3+1); f[0][0]=a1[0]=a[2]-a[1]; f[0][1]=a1[1]=a[3]-a[2]; f[1][0]=b1[0]=b[2]-b[1]; f[1][1]=b1[1]=b[3]-b[2]; deep=1; deep1=1; while(a1[0]!=a1[1]) { long long k=0,p; if(a1[0]>a1[1]) { p=a1[1]; if(!(a1[0]%a1[1])) { k=a1[0]/a1[1]-1; deep+=k; a1[0]-=k*a1[1]; } else { k=a1[0]/a1[1]; deep+=k; a1[0]%=a1[1]; } } else { p=a1[0]; if(!(a1[1]%a1[0])) { k=a1[1]/a1[0]-1; deep+=k; a1[1]-=k*a1[0]; } else { k=a1[1]/a1[0]; deep+=k; a1[1]%=a1[0]; } } } while(b1[0]!=b1[1]) { long long k=0,p; if(b1[0]>b1[1]) { p=b1[1]; if(!(b1[0]%b1[1])) { k=b1[0]/b1[1]-1; deep1+=k; b1[0]-=k*b1[1]; } else { k=b1[0]/b1[1]; deep1+=k; b1[0]%=b1[1]; } } else { p=b1[0]; if(!(b1[1]%b1[0])) { k=b1[1]/b1[0]-1; deep1+=k; b1[1]-=k*b1[0]; } else { k=b1[1]/b1[0]; deep1+=k; b1[1]%=b1[0]; } } } sort(a+1,a+3+1); sort(b+1,b+3+1); if(deep>deep1) { deep=deep^deep1; deep1=deep^deep1; deep=deep^deep1; f[0][0]=f[0][0]^f[1][0]; f[1][0]=f[0][0]^f[1][0]; f[0][0]=f[0][0]^f[1][0]; f[0][1]=f[0][1]^f[1][1]; f[1][1]=f[0][1]^f[1][1]; f[0][1]=f[0][1]^f[1][1]; a[1]=a[1]^b[1]; b[1]=a[1]^b[1]; a[1]=a[1]^b[1]; a[2]=a[2]^b[2]; b[2]=a[2]^b[2]; a[2]=a[2]^b[2]; a[3]=a[3]^b[3]; b[3]=a[3]^b[3]; a[3]=a[3]^b[3]; } ans=deep1-deep; while(deep<deep1) { long long k=0; if(f[1][0]>f[1][1]) { if(f[1][0]%f[1][1]==0) k--; k+=f[1][0]/f[1][1]; long long p=f[1][1]; if(deep1-k>=deep) { f[1][0]-=k*f[1][1]; deep1-=k; b[3]-=(k-k/2)*p*2; b[2]-=(k/2)*p*2; } else { f[1][0]-=(deep1-deep)*f[1][1]; k=deep1-deep; b[3]-=(k-k/2)*p*2; b[2]-=(k/2)*p*2; break; } } else { if(f[1][1]%f[1][0]==0) k--; k+=f[1][1]/f[1][0]; long long p=f[1][0]; if(deep1-k>=deep) { f[1][1]-=k*f[1][0]; b[1]+=(k-k/2)*p*2; b[2]+=(k/2)*p*2; deep1-=k; } else { f[1][1]-=(deep1-deep)*f[1][0]; k=deep1-deep; b[1]+=(k-k/2)*p*2; b[2]+=(k/2)*p*2; break; } } } deep1=deep; dd=deep; sort(a+1,a+3+1); sort(b+1,b+3+1); for(long long i=33;i>=0;i--) { if(mi[i]<=dd) { q=true; l=f[0][0]; r=f[0][1]; for(long long j=1;j<=n;j++) a1[j]=a[j]; do1(mi[i]); if(q) { ll=f[1][0]; rr=f[1][1]; for(long long j=1;j<=n;j++) b1[j]=b[j]; do2(mi[i]); if(q) { sort(a+1,a+3+1); sort(b+1,b+3+1); if(a[1]==b[1] && a[2]==b[2] && a[3]==b[3]) { for(long long j=1;j<=n;j++) a[j]=a1[j]; for(long long j=1;j<=n;j++) b[j]=b1[j]; continue; } f[0][0]=a[2]-a[1]; f[0][1]=a[3]-a[2]; f[1][0]=b[2]-b[1]; f[1][1]=b[3]-b[2]; ans+=mi[i]*2; } else { for(long long j=1;j<=n;j++) a[j]=a1[j]; for(long long j=1;j<=n;j++) b[j]=b1[j]; } } else { for(long long j=1;j<=n;j++) a[j]=a1[j]; } } } if(a[1]==b[1] && a[2]==b[2] && a[3]==b[3]) { printf("YES\n%lld",ans); return 0; } l=f[0][0]; r=f[0][1]; do1(1); ll=f[1][0]; rr=f[1][1]; do2(1); sort(a+1,a+3+1); sort(b+1,b+3+1); ans+=2; if(a[1]==b[1] && a[2]==b[2] && a[3]==b[3]) printf("YES\n%lld",ans); else printf("NO"); }
【NOIP2016提高A組模擬8.15】Throw