题目描述
由于晨晨还没有研究出核心算法,在游戏中总是被明明击败。晨晨拿出了杀手锏进行反击,精心设计了一个大型取数字求位置的难题:NN( N是奇数)个地砖,每个上面写有一个编号,这些编号正好是1到N平方。她把这些地砖按次序从中间开始螺旋的铺垫在地上,形成一个NN的正方形。N=5时如下图:
每块地砖的位置用行列编号表示。左上的地砖位置为第一行第一列,右下的地砖位置为第N行第N列。上图中编号3的地砖在第2行第3列。
如果一块地砖在X行Y列,则位置编码为XN+Y。例如:上图中编号是1的地址位置编码是:53+3 = 18;编号是5的地址位置编码是:5*3+4 = 19。
晨晨要明明计算,从数A的位置编码是什么。比如:N=5,A=6,为: 24
每次提问前,晨晨想知道正确的答案,请编程计算出位置编码。
输入
第一行:1个奇数N。
第二行:1个整数A。(0<A<=N*N)
输出
一个整数,表示编号A地砖的位置编码。
样例输入 Copy
5
20
样例输出 Copy
28
提示
数据范围:80%数据0<N<1000; 100%数据0<N<100000.
题意分析:由于0<N<1000000所以可定不能暴力。一开始我是找数字与坐标的函数关系。但只能发现由内到外左上角都是n2+1;和走一圈到最后是(n+1)2.之后就想到了分块。但我刚开始时并非正解的分,可能原本思路对,但我没做出来
上面5个一块。下面五个一块,左右各一块。可是没做出来,后来参考
@Frozen_Guardian,献上大佬的原文https://blog.csdn.net/qq_45458915/article/details/103108251
中间有点没搞明白,就是&的使用。
考完正解思路立马清醒。一共分四块,
然后 分类讨论一下即可
注意一下,这个题目会爆int,所以所有数据都用longlong就ok了,还有递归在层数等于1的时候记得特判一下就没问题了
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL x,y;
void f(LL a,LL b) {
LL l=(b-2)*(b-2);//次外层
LL d=b*b;//最外层
if(b==1) {//单独考虑为一层时这种情况。
x=y=1;
return;
}
if(a>l&&a<=d) {//判断是否在最外层
if(a>l&&a<=l+(b-1)) {//第一种情况
x=1;
y=a-l;
return;
} else if(a>l+(b-1)&&a<=l+2*(b-1)) {//第二种情况
y=b;
x=a-(l+b-1);
return;
} else if(a>l+2*(b-1)&&a<=l+3*(b-1)) {//第三种情况
x=b;
y=b-(a-(l+2*(b-1)))+1;//b-后面的保证列正确
return;
} else {//第四种情况
y=1;
x=b-(a-(l+3*(b-1)))+1;//用b-后面的保证行正确
return;
}
} else {
f(a,b-2);//由外层到内层
x++;//进一层x和y都会减一所以在后面加上。
y++;
return;
}
}
int main() {
LL n,m;
scanf("%lld%lld",&n,&m);
f(m,n);
printf("%lld\n",n*x+y);//输出位置
return 0;
}