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的主要内容,如果未能解决你的问题,请参考以下文章

NOIP2016提高A组模拟8.15Garden

Jzoj4742NOIP2016提高A组模拟9.2快速幂单峰

NOIP2016提高A组模拟10.15总结

NOIP2016提高A组模拟8.14总结

NOIP2016提高A组模拟9.17序列

NOIP2016提高A组模拟7.17寻找