【BZOJ2144】【JZOJ4701】Throw
来源:互联网 发布:08-09年nba总决赛数据 编辑:程序博客网 时间:2024/05/23 01:20
Description
原题是【BZOJ2144】跳跳棋
Solution
我们设一个状态:
设
那么如果是
如果是两边往中间条,那就是:
把每种状态弄出来,形成了一颗树!
但是直接这样找会超时。
其实,由于可以顺操作和逆操作是一样的,那么从起始位置到目标位置的距离其实就是它们在一棵状态树上的距离。
那么就是一个求最近公共祖先的问题了。
但是,树的深度太大,不能预处理出倍增数组,这就尴尬了。
其实一点都不尴尬,我们再设一个二元组状态
那么一次转移:
这是辗转相减法?
于是可以用辗转相除的思想优化。
那么一次转移就变成了:
那么没有倍增数组怎么倍增呢?
假如我们要跳
当然,我们还需保留三元组信息用于判断。
时间复杂度
Code
#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<algorithm>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define N 10using namespace std;int a[N],b[N];int c[N],d[N];int ans=0;void pre(){ fo(i,1,3) c[i]=a[i]; fo(i,1,3) d[i]=b[i]; c[4]=c[2]-c[1]; c[5]=c[3]-c[2]; d[4]=d[2]-d[1]; d[5]=d[3]-d[2];}int turn(int x,int y){ if(x%y==0) return x/y-1; else return x/y;}void jump(int x,bool is){ int p1=4,p2=5,q1=4,q2=5; int t1=1<<x,t2=1<<x; int l1=c[4],r1=c[5],l2=d[4],r2=d[5]; int a1=c[1],a2=c[2],a3=c[3]; int b1=d[1],b2=d[2],b3=d[3]; while(t1 || t2) { if(c[4]>c[5]) { if(t1>=turn(c[4],c[5])) t1-=turn(c[4],c[5]),c[4]=c[4]-turn(c[4],c[5])*c[5]; else c[4]=c[4]-t1*c[5],t1=0; c[2]=c[1]+c[4]; c[3]=c[2]+c[5]; } else if(c[5]>c[4]) { if(t1>=turn(c[5],c[4])) t1-=turn(c[5],c[4]),c[5]=c[5]-turn(c[5],c[4])*c[4]; else c[5]=c[5]-t1*c[4],t1=0; c[2]=c[3]-c[5]; c[1]=c[2]-c[4]; } if(d[4]>d[5]) { if(t2>=turn(d[4],d[5])) t2-=turn(d[4],d[5]),d[4]=d[4]-turn(d[4],d[5])*d[5]; else d[4]=d[4]-t2*d[5],t2=0; d[2]=d[1]+d[4]; d[3]=d[2]+d[5]; } else if(d[5]>d[4]) { if(t2>=turn(d[5],d[4])) t2-=turn(d[5],d[4]),d[5]=d[5]-turn(d[5],d[4])*d[4]; else d[5]=d[5]-t2*d[4],t2=0; d[2]=d[3]-d[5]; d[1]=d[2]-d[4]; } if(c[4]==c[5] && d[4]==d[5]) break; } if(c[1]==d[1] && c[2]==d[2] && c[3]==d[3]) { if(is) { c[1]=a1,c[2]=a2,c[3]=a3,c[4]=l1,c[5]=r1; d[1]=b1,d[2]=b2,d[3]=b3,d[4]=l2;d[5]=r2; } else if(!is) ans+=2; } else ans+=(1<<x)*2;}int main(){ fo(i,1,3) scanf("%d",&a[i]); fo(i,1,3) scanf("%d",&b[i]); sort(a+1,a+4); sort(b+1,b+4); pre(); int dep1=0,dep2=0; while(c[4]!=c[5]) { if(c[4]>c[5]) { dep1+=turn(c[4],c[5]),c[4]=c[4]-turn(c[4],c[5])*c[5]; c[2]=c[1]+c[4]; c[3]=c[2]+c[5]; } else if(c[5]>c[4]) { dep1+=turn(c[5],c[4]),c[5]=c[5]-turn(c[5],c[4])*c[4]; c[2]=c[3]-c[5]; c[1]=c[2]-c[4]; } } while(d[4]!=d[5]) { if(d[4]>d[5]) { dep2+=turn(d[4],d[5]),d[4]=d[4]-turn(d[4],d[5])*d[5]; d[2]=d[1]+d[4]; d[3]=d[2]+d[5]; } else if(d[5]>d[4]) { dep2+=turn(d[5],d[4]),d[5]=d[5]-turn(d[5],d[4])*d[4]; d[2]=d[3]-d[5]; d[1]=d[2]-d[4]; } } if(c[1]!=d[1] || c[2]!=d[2] || c[3]!=d[3]) { cout<<"NO"; return 0; } pre(); if(dep1>dep2) { int t=dep1-dep2; ans+=t; while(t) { if(c[4]>c[5]) { if(t>=turn(c[4],c[5])) t-=turn(c[4],c[5]),c[4]=c[4]-turn(c[4],c[5])*c[5]; else c[4]=c[4]-t*c[5],t=0; c[2]=c[1]+c[4]; c[3]=c[2]+c[5]; } else if(c[5]>c[4]) { if(t>=turn(c[5],c[4])) t-=turn(c[5],c[4]),c[5]=c[5]-turn(c[5],c[4])*c[4]; else c[5]=c[5]-t*c[4],t=0; c[2]=c[3]-c[5]; c[1]=c[2]-c[4]; } } dep1=dep2; } else { int t=dep2-dep1; ans+=t; while(t) { if(d[4]>d[5]) { if(t>=turn(d[4],d[5])) t-=turn(d[4],d[5]),d[4]=d[4]-turn(d[4],d[5])*d[5]; else d[4]=d[4]-t*d[5],t=0; d[2]=d[1]+d[4]; d[3]=d[2]+d[5]; } else if(d[5]>d[4]) { if(t>=turn(d[5],d[4])) t-=turn(d[5],d[4]),d[5]=d[5]-turn(d[5],d[4])*d[4]; else d[5]=d[5]-t*d[4],t=0; d[2]=d[3]-d[5]; d[1]=d[2]-d[4]; } } dep2=dep1; } if(c[1]==d[1] && c[2]==d[2] && c[3]==d[3]) { cout<<"YES"<<endl; cout<<ans; return 0; } int p=log2(dep1); fd(i,p,0) jump(i,1); jump(0,0); if(c[1]==d[1] && c[2]==d[2] && c[3]==d[3]) { cout<<"YES"<<endl; cout<<ans; } else cout<<"NO"<<endl;}
2 0
- 【BZOJ2144】【JZOJ4701】Throw
- 【BZOJ2144】Throw 数论
- JZOJ4701. 【NOIP2016提高A组模拟8.15】Throw
- 【NOIP2016提高A组模拟8.15】Throw(BZOJ2144)
- throw
- throw()
- throw
- throw
- Throw
- Throw
- 【BZOJ2144】跳跳棋
- 【杂题】bzoj2144跳跳棋
- bzoj2144 LCA+二分
- 【bzoj2144】跳跳棋
- [bzoj2144]: 跳跳棋
- [bzoj2144]跳跳棋 LCA
- bzoj2144 跳跳棋 二分+lca
- bzoj2144 跳跳棋 二分&lca 神题
- 构建子类,初始化父类(执行顺序n
- 浅析对象
- Eclipse 与 Git
- 计算机永远无法超越人类——从李世石与阿尔法的人机大战中想到的
- 导入工程出现@Override错误
- 【BZOJ2144】【JZOJ4701】Throw
- 继承中类加载的顺序
- jquery实现擦除效果
- 2016中国大学生程序设计竞赛 - 网络选拔赛 1001
- 判断线段相交
- 引用与函数默认参数
- UVA-10340
- 【杭电oj2043】密码
- 1、Java的String类使用