NOIP2016提高A组模拟8.15Throw
Posted 无尽的蓝黄
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2016提高A组模拟8.15Throw相关的知识,希望对你有一定的参考价值。
题目
分析
首先对于一个状态(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.15Throw的主要内容,如果未能解决你的问题,请参考以下文章