【NOIP2016提高A组模拟8.15】Throw

题目

这里写图片描述

分析

首先对于一个状态(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{egin{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} ight. ]

我们将一个状态两边向中间转移后的状态设为这个状态的父亲,我们发现,这刚好形成了一颗树。
那么从起点和终点都分别向父亲跳,用hash判重,如果有交点就输出yes以及ans,反之。
但这显然会超时。
我们用二元组(l,r)来代表每一个状态,l=b-a,r=c-b。(显然根节点就是l=r的二元组)
当这个状态向父亲跳时,就变成

[left{egin{array}\l>r,(l,r)-->(l-r,r) \l<r,(l,r)-->(l,r-l) end{array} ight. ]

发现这样转移就类似于辗转相除法!
用倍增求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
%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
%lld",ans);
		else printf("NO");
}
原文地址:https://www.cnblogs.com/chen1352/p/9045290.html