// 此题可用数学方法解决,复杂度O(n)。
// 观察规律如下:
// 1 1 1*1 1 2*1-1
// 1 1 2 1*1+1 2 2*1
// 1 2 1 4 2*2 3 2*2-1
// 1 2 2 1 6 2*2+2 4 2*2
// 1 2 3 2 1 9 3*3 5 2*3-1
// 1 2 3 3 2 1 12 3*3+3 6 2*3
参考程序:
#include <cstdio>
#include <cmath>
using namespace std;
int main()
{
long n,x,y;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d %d",&x,&y);
long m=y-x,l=long(sqrt(m));
if(m==0) printf("0\n");
else if(m==l*l) printf("%d\n",2*l-1);
else if(m<=l*l+l) printf("%d\n",2*l);
else printf("%d\n",2*(l+1)-1);
}
return 0;
}
坑的一题,本来以为可以DFS暴一把,结果一看数据范围 2的31次方...., 直接放弃,后来看了discuss.
下面的解释比较清晰:列出了2n-1步 和 2n步最多能走多少步 L1 和 L2, 那么对于距离S, 当 L1<S<=L2时, 能走过此距离S的最少步数就是2n步(因为2n-1步最多也走不了这么多,但是对于S,一定有2n步可以走出来),而对于距离N来说,观察下面规律,其应该走的步数V:
long b = sqrt(N)
如果 N = b*b, 那么 就是 2b-1步
否则如果 N < b*b+b, 那么就是2b步(n*n<=L<=n*n+n, 那么sqrt(L)取整b就是n, 那么就取值2b)
否则就是2(b+1)-1步(下面的例子中,对于距离 n*n+n<L<(n+1)*(n+1), sqrt(L)以后取整的b还是n, 那么会有b*b+b > L, 那么应该取值 2b+1)
1+2+...+n-1+n+n-1+..+1 和为 n ×n 对应 2n-1 步 . .期间对应为 2n 步 . 1+2+...+n-1+n+n+n-1+..+1 和为 n * n +n 对应 2n 步 . .期间对应为 2n+1 步 . 1+2+...+n+n+1+n+..+1 和为 (n+1) ×(n+1) 对应 2n+1 步 0输出为0.
对于上面的 “ 2n-1步 和 2n步最多能走多少步 L1 和 L2 当 L1<S<=L2时, 能走过此距离S的最少步数就是2n步”
证明其实也简单,2n-1和 2n之间的间隔步数是 n*n+1 到 n*n +n + 1, 那么如何将 n*n+n在满足题意的要求下变为n*n+K(1<=K<=n-1)
也很简单:如果K == n-1, 那么序列变为
1+2+...+n-1+n-1+n-1+...+2+1
如过K == n-2:
1+2+...+n-1+n-1+n-2+ n-2+...+2+1
类推K == 1:
1+2+...+n-1+n-1+n-2+n-3+n-4+..+1+1
该题虽然算是水题,不过思想还是挺好的,先列出每个解可能的上限值,然后根据实际值的分布来确定落在哪个解.