• bzoj2144: 跳跳棋


    昨天考试的神仙题

    对于一个状态(x,y,z),有三种转移方案,往外跳两种,往里跳只有1种(考试的时候没有意识到)

    那么可以看作一棵树,往外跳是子节点,往里跳是父亲

    问题转换成树上两个点求最短路,这样就只用往里面跳了

    考虑往里面跳是相当于一个辗转相除的,复杂度是logK,根据求LCA倍增的思想,不停往上跳就好。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    bool check(int ax,int ay,int az,int bx,int by,int bz)
    {
        int t1,t2,w;
        
        t1=ay-ax,t2=az-ay,w=0;
        if(t1>t2){swap(t1,t2);w^=1;}
        
        while((t2-1)/t1>0)
        {
            int c=(t2-1)/t1;
            
            if(w==0){ax+=c*t1;ay+=c*t1;}
            else     {ay-=c*t1,az-=c*t1;}
            
            t2=t2-t1*c;
            swap(t1,t2);w^=1;
        }
        
        t1=by-bx,t2=bz-by,w=0;
        if(t1>t2){swap(t1,t2);w^=1;}
        
        while((t2-1)/t1>0)
        {
            int c=(t2-1)/t1;
            
            if(w==0){bx+=c*t1;by+=c*t1;}
            else     {by-=c*t1;bz-=c*t1;}
            
            t2=t2-t1*c;
            swap(t1,t2);w^=1;
        }
        
        return ax==bx&&ay==by&&az==bz;
    }
    
    int getdep(int x,int y,int z)
    {
        int t1=y-x,t2=z-y,ret=0;
        if(t1>t2)swap(t1,t2);
        while((t2-1)/t1>0)
        {
            int c=(t2-1)/t1;
            ret+=c;
            t2=t2-t1*c;
            swap(t1,t2);
        }
        return ret;
    }
    void jumpK(int &x,int &y,int &z,int d)
    {
        int t1=y-x,t2=z-y,w=0;
        if(t1>t2){swap(t1,t2);w^=1;}
        while(d>0)
        {
            int c=min(d,(t2-1)/t1);
            d-=c;
            
            if(w==0){x+=c*t1;y+=c*t1;}
            else     {y-=c*t1,z-=c*t1;}
            
            t2=t2-t1*c;
            swap(t1,t2);w^=1;
        }
    }
    int main()
    {
        freopen("2.in","r",stdin);
        freopen("2.out","w",stdout);
        int ax,ay,az,bx,by,bz;
        scanf("%d%d%d%d%d%d",&ax,&ay,&az,&bx,&by,&bz);
        if(ax>ay)swap(ax,ay);                     if(bx>by)swap(bx,by);
        if(ax<az&&az<ay)swap(ay,az);              if(bx<bz&&bz<by)swap(by,bz);
        if(az<ax)swap(ay,az),swap(ax,ay);         if(bz<bx)swap(by,bz),swap(bx,by);
        
        if(!check(ax,ay,az,bx,by,bz)){printf("NO
    ");return 0;}
        else printf("YES
    ");
        
        //--------------------------------------
        
        int da=getdep(ax,ay,az),db=getdep(bx,by,bz);
        int ans=0;
        if(da!=db)
        {
            if(da<db)swap(da,db),swap(ax,bx),swap(ay,by),swap(az,bz);
            ans+=da-db;
            jumpK(ax,ay,az,da-db);
        }
        if(ax==bx&&ay==by&&az==bz){printf("%d
    ",ans);return 0;}
        for(int i=30;i>=0;i--)
            if(db>(1<<i))
            {
                int tax=ax,tay=ay,taz=az;
                int tbx=bx,tby=by,tbz=bz;
                jumpK(ax,ay,az,(1<<i));
                jumpK(bx,by,bz,(1<<i));
                if(ax==bx&&ay==by&&az==bz)
                {
                    ax=tax,ay=tay,az=taz;
                    bx=tbx,by=tby,bz=tbz;
                }
                else ans+=(1<<i)*2,db-=(1<<i);
            }
        printf("%d
    ",ans+2);
        return 0;
    }
  • 相关阅读:
    题解 CF934A 【A Compatible Pair】 ——贪心
    洛谷 P3381 【【模板】最小费用最大流】
    洛谷 P3376 【【模板】网络最大流】
    洛谷 P1027 【Car的旅行路线】
    TYVJ P1039 【忠诚2】
    洛谷 P1273 【有线电视网】
    斯特林数相关
    从 简单容斥 到 min-max 容斥 与 二项式反演
    POI2011 Lightning Conductor
    LOJ6089 小 Y 的背包计数问题
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9578087.html
Copyright © 2020-2023  润新知