题目链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4833
----------------------------------------------------------------------------分割线------------------------------------------------------------------------
题意简单明了。就是按照回形蛇数填充n*n的矩阵,给你一个数K,问K的位置在第几行第几列。
----------------------------------------------------------------------------分割线------------------------------------------------------------------------
表示数学不行,我只能把找位置分成几个部分:走完一圈的,走完一条线的,走不完一条线的。
1.对于走完一圈的。我们可以轻易得到第k圈的大小为4*(n-k*2)-4; 然后在写题过程中,我是从第0圈开始的。然后各种艰难。但是目前没尝试从第1圈开始搞。这份题解也是把第0圈当成第1圈写的。
2.对于走一条线的。假设我们现在是在第k圈,那么我们可以得到一条线的长度为n-2*k,n-2*k-1,n-2*k-1,n2*k-2对于最后一个,我们不考虑。因为我们是通过第一步得到它一定在某个圈内。然后我们走了前面三个,如果没有走到的话,一定在第四个里面。
3.其实就是最后面额外处理就好了。
---------------------------------------------------------------------------分割线-------------------------------------------------------------------------
再详细补充坑点:
1.对于第一个。我第一圈是0的说我的式子是:4*(n-2*k)-4;
2.对于第二个要求,我们需要得到它位于第几圈,所以我们需要求这个。
1).通过等差数列求和。假设它完整的走完了k圈,我们可以得到sum=4*(k-1)*(n-k-1)<=K,要求k的最大值
2).通过上面的式子,我们知道sum是一个关于k的一元二次函数,并且开口是向下的,根据题意,sum应该 是要越来越大,所以只能拿递增的部分。
3).如何解那个方程?表示懒得想,所以我用了二分去搞,由于只能取递增的部分,所以记得二分的上界不 能大于极大值点,也就是(n-2)/2;
4).解完方程就解决了?不不不,还有一个问题,假设没走完一圈的话,结果其实也是0,因为下界是0。
那么得到0的情况下,就不一定走完第0圈了,所以我们分个类讨论下。
5).解决了0圈之后,那么接下来就是预想的走完了k圈了。那么接下来就是模拟走线了。最简单的4个if解 决,或者想办法写成循环什么的。
写到这里应该都总结完了。
---------------------------------------------------------------------分割线---------------------------------------------------------------------------
贴代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
int dx[]= {0,1,0,-1};
int dy[]= {1,0,-1,0};
long long f(long long n,long long mid)
{
return 4*(mid+1)*(n-mid-1);
}
int main()
{
long long n,k;
while(scanf("%lld%lld",&n,&k)!=EOF) {
if(n==1) {
printf("%lld %lld\n",1,1);
continue;
}
long long l=0,r=(n-2)/2;
long long mid=l+r>>1;
while(l<r) {
mid=(l+r+1)>>1;
long long an=f(n,mid);
if(an<=k) {
l=mid;
} else
r=mid-1;
}
long long now;
long long nx,ny;
if(f(n,0)>=k) {
now=n;
nx=1;
ny=0;
} else {
now=n-l*2-2;
k-=f(n,l);
long long quan=l+1;
ny=quan,nx=ny+1;
}
int i=0;
if(k<=now) {
nx+=dx[i]*k;
ny+=dy[i]*k;
printf("%lld %lld\n",nx,ny);
continue;
} else {
k-=now;
nx+=dx[i]*now;
ny+=dy[i]*now;
now--;
i++;
}
for(; i<3&&k>=now; i++) {
k-=now;
nx+=dx[i]*now;
ny+=dy[i]*now;
}
nx+=dx[i]*k;
ny+=dy[i]*k;
printf("%lld %lld\n",nx,ny);
}
return 0;
}