[数学] uva 12954 Spiral

题目链接:

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值