Solution: (不理解时对着图研究一下就清楚啦!!!)
sm[i]为|D(i)| (x,y,n)为x,y在D(n)中的最短路
已知sm[i-1]+1为D(i)的割点
于是x-y的最短路就可以分为三种情况:
- x<sm[n-1]+1&&y>=sm[n-1]+1
- x<sm[n-1]+1&&y<sm[n-1]+1
- x>=sm[n-1]+1&&y>=sm[n-1]+1
下面我们就来讨论这三种情况
- x在图D(n-1)上,y在图D(n-2)上,它们的最短路必过割点sm[n-1]+1
我们只要分别求解x,y到割点的最短路即可
y到割点的最短路即为(1,y-sm[n-1],n-2)
x到割点的最短路却有两种可能 (1,x,n-1)+1或(x,sm[n-1],n-1)+1 这两种情况取小即可
- x,y都在图D(n-1)上
一定要注意这里 x-y的最短路并不一定局限于D(n-1) 还有可能经过割点
所以这里有两种情况:(x,y,n-1)
又有两种经过割点的方式: (1,x,n-1)+(y,sm[n-1],n-1)+2 和 (1,y,n-1)+(x,sm[n-1],n-1)+2
同样取小即可
- x,y都在图D(n-2)上
是最简单的一种情况啊,为(x,y,n-2)
但是如果这样子递归下去是会TLE的,所以我们要优化一下
发现只要求出图D(i)中x,y点到1和sm[i]的最短路就可以了
于是预处理出就可以了
d1[i]为(1,x,i) d2[i]为(x,sm[i],i) d3[i]为(1,y,i) d4[i]为(y,sm[i],i)
pre函数看图研究一下就可以理解啦
CODE:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define R register 5 #define go(i,a,b) for(R int i=a;i<=b;i++) 6 #define ll long long 7 #define M 105 8 using namespace std; 9 ll rd() 10 { 11 ll x=0,y=1;char c=getchar(); 12 while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} 13 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();} 14 return x*y; 15 } 16 ll T,n,sm[M],d[M],d1[M],d2[M],d3[M],d4[M]; 17 void pre(ll x,ll nw,ll t1[],ll t2[]) 18 { 19 if(nw==0) return ; 20 if(nw==1) {t1[1]=(x==2);t2[1]=(x==1);return ;} 21 if(x<=sm[nw-1]) 22 { 23 pre(x,nw-1,t1,t2); 24 t1[nw]=min(t1[nw-1],t2[nw-1]+2); 25 t2[nw]=min(t1[nw-1],t2[nw-1])+d[nw-2]+1; 26 } 27 else 28 { 29 pre(x-sm[nw-1],nw-2,t1,t2); 30 t1[nw]=t1[nw-2]+1; 31 t2[nw]=t2[nw-2]; 32 } 33 } 34 ll qy(ll x,ll y,ll nw) 35 { 36 if(nw<=1) return x!=y; 37 if(x<sm[nw-1]+1&&y>=sm[nw-1]+1) return min(d1[nw-1],d2[nw-1])+d3[nw-2]+1; 38 if(x<sm[nw-1]+1&&y<sm[nw-1]+1) return min(qy(x,y,nw-1),min(d1[nw-1]+d4[nw-1],d2[nw-1]+d3[nw-1])+2); 39 return qy(x-sm[nw-1],y-sm[nw-1],nw-2); 40 } 41 int main() 42 { 43 freopen("1.in","r",stdin); 44 freopen("1.out","w",stdout); 45 T=rd();n=rd();n=min(n,(ll)80); 46 sm[0]=1;sm[1]=2;d[0]=0;d[1]=1;//d[i]表示D(i)的1到sm[i]结点的最短距离 47 go(i,2,n) sm[i]=sm[i-1]+sm[i-2],d[i]=d[i-2]+1;n=min(n,(ll)80); 48 while(T--) 49 { 50 ll x=rd(),y=rd();if(x>y)swap(x,y); 51 pre(x,n,d1,d2);pre(y,n,d3,d4); 52 printf("%lld ",qy(x,y,n)); 53 } 54 return 0; 55 }
后:
真的没那么难啊 仔细分析细心一点就没有问题啦
然而 我还是调了一晚上qwq 因为longlong 要哭了...
如果哪里不懂一定要问我 因为可能我也不懂那我就要感谢你发现我没懂的地方啦
然后我们可以一起研究啦啦啦