题意:三个数字,每个数字可以以一个数字为中心,翻转到另一边(只能翻过一个数字),给你两个三元组,问一个变成另一个最少需要几步
思路:三个数字,中间的往两边翻的话,边上两个数字,相互交替,无穷无尽。如果,边上的往中间翻的话,总会结束。结束的时候就是它的根。那我们,找到它们的根,根相同,去找它们的步数,可能没走到根,它们就一样了。先让它们走到同一深度,再二分,mid步都相同,r = mid;否则,l = mid+1。这些还不是关键,关键的是翻的速度,比如三个数1、2、101,我们不能一步步翻(2、3、101; 3、4、101……),这样太慢了,能不能直接翻到99、100、101。假若左边间隔d1 > 右边间隔d2,步数s = (d1-1) / d2; a1 -= s * d2,a2 -=s * d2 (三个数为a0,a1,a2,已排序);d1 < d2同理。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<list>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<numeric>
#include<functional>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 3;
int a[maxn],b[maxn],c[maxn],d[maxn];
int fa[maxn][maxn];
int fid(int x)
{
if(x == 1)
memcpy(a,c,3*sizeof(int));
else
memcpy(a,d,3*sizeof(int));
int t = 0,dis;
sort(a,a+3);
int d1,d2;
d1 = a[1] - a[0];
d2 = a[2] - a[1];
while( d1 != d2)
{
if(d1 < d2)
{
dis = (d2-1) / d1;
a[1] += dis*d1;
a[0] += dis*d1;
t += dis;
}
else
{
dis = (d1-1) / d2;
a[2] -= dis * d2;
a[1] -= dis * d2;
t += dis;
}
sort(a,a+3);
d1 = a[1] - a[0];
d2 = a[2] - a[1];
}
fa[x][0] = a[0];
fa[x][1] = a[1];
fa[x][2] = a[2];
return t;
}
void go(int a[],int t)
{
int dis;
sort(a,a+3);
int d1,d2;
d1 = a[1] - a[0];
d2 = a[2] - a[1];
while(t)
{
if(d1 < d2)
{
dis = (d2-1) / d1;
if(dis > t)
dis = t;
a[1] += dis*d1;
a[0] += dis*d1;
t -= dis;
}
else
{
dis = (d1-1) / d2;
if(dis > t)
dis = t;
a[2] -= dis * d2;
a[1] -= dis * d2;
t -= dis;
}
sort(a,a+3);
d1 = a[1] - a[0];
d2 = a[2] - a[1];
}
}
int check(int t)
{
int dis;
memcpy(a,c,3*sizeof(int));
memcpy(b,d,3*sizeof(int));
int tt = t;
sort(a,a+3);
int d1,d2;
d1 = a[1] - a[0];
d2 = a[2] - a[1];
while(t)
{
if(d1 < d2)
{
dis = (d2-1) / d1;
if(dis > t)
dis = t;
a[1] += dis*d1;
a[0] += dis*d1;
t -= dis;
}
else
{
dis = (d1-1) / d2;
if(dis > t)
dis = t;
a[2] -= dis * d2;
a[1] -= dis * d2;
t -= dis;
}
sort(a,a+3);
d1 = a[1] - a[0];
d2 = a[2] - a[1];
}
sort(b,b+3);
d1 = b[1] - b[0];
d2 = b[2] - b[1];
while(tt)
{
if(d1 < d2)
{
dis = (d2-1) / d1;
if(dis > tt)
dis = tt;
b[1] += dis*d1;
b[0] += dis*d1;
tt -= dis;
}
else
{
dis = (d1-1) / d2;
if(dis > tt)
dis = tt;
b[2] -= dis * d2;
b[1] -= dis * d2;
tt -= dis;
}
sort(b,b+3);
d1 = b[1] - b[0];
d2 = b[2] - b[1];
}
if(a[0] == b[0] && a[1] == b[1] && a[2] == b[2] )
return 1;
else
return 0;
}
void bir(int l,int r,int have)
{
while(l < r)
{
int mid = (l+r) / 2;
if(check(mid))
r = mid;
else
l = mid+1;
}
printf("%d\n",2*l+have);
}
int main(void)
{
while(scanf("%d%d%d",&c[0],&c[1],&c[2])!=EOF)
{
scanf("%d%d%d",&d[0],&d[1],&d[2]);
int num1 = fid(1);
int num2 = fid(2);
if(fa[1][0] == fa[2][0] && fa[1][1] == fa[2][1] && fa[1][2] == fa[2][2])
{
printf("YES\n");
if(num1 < num2)
{
go(d,num2-num1);
bir(0,min(num1,num2),num2-num1);
}
else
{
go(c,num1-num2);
bir(0,min(num1,num2),num1-num2);
}
}
else
printf("NO\n");
}
return 0;
}