poj-2590

26 篇文章 0 订阅
// 此题可用数学方法解决,复杂度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

该题虽然算是水题,不过思想还是挺好的,先列出每个解可能的上限值,然后根据实际值的分布来确定落在哪个解.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值