蓝桥杯题目:方格计数

群里有小伙伴分享了一道蓝桥杯的题目:
方格计数
乍一看,以为会有什么巧妙的解法。实则是一道暴力求解题。

  • 根据对称性,先求得第一象限内满足条件的小方格数,再乘以4即得到答案;

  • 第一象限内,每个小方格的右上顶点,是这个小方格上距离圆心最远的点。即是说右上顶点在圆内,小方格也会在圆内

(想想为什么?不妨设右上顶点坐标为(p,q)(p>=1,q>=1),则其余3个顶点坐标分别为(p-1,q-1),(p,q-1),(p-1,q)

  • 每个右上顶点刚好一一对应到一个小方格

  • 根据点在圆内的理论:点(p,q)在圆内的充要条件是p^2+q^2<r^2,其中圆的圆心是原点(0,0),半径是r

结论:计算第一象限内到圆心的距离不超过r的点(x,y)(x>=1,y>=1)的个数,再乘以4即是答案。

方法1:

public static int count1() {
    int r2 = 1000*1000;
    int count = 0;
    for (int i = 1; i <= 1000; i++) {
        for (int j = 1; j <= 1000; j++) {
            if(i*i + j*j <= r2) {
                count++;
            }
        }
    }
    return count*4;//3137548
}

方法2:

public static int count2() {
    int r2 = 1000*1000;
    // 小优化:0.7^2+0.7^2 < 1
    // (1,1)--(700,700)范围内的点必然在圆内
    int count = 700*700;
    for (int i = 701; i <= 1000; i++) {
        for (int j = 1; j <= 700; j++) {
            if(i*i + j*j <= r2) {
                count += 2;
            }
        }
    }
    for (int i = 701; i <=1000 ; i++) {
        for (int j = 701; j <=1000 ; j++) {
            if(i*i + j*j <= r2) {
                count++;
            }
        }
    }
    return count*4;//3137548
}

方法3:

特别感谢群里另一位小伙伴分享的这种优雅的解答。这种实现相比前2种,其效率提升在10倍以上

其思路是,遍历可能的横坐标x,求得圆上的点(x, y),其中y=sqrt(r*r-x*x)),y向下取整其实就是这一列上符合条件的方格数。

public static int count3() {
    int sum = 0;
    for (int x = 1; x <= 1000; x++) {
        sum += (int)Math.sqrt(1000000-x*x);
    }
    return sum*4;//3137548
}

PS:Math.sqrt()底层实现上,采用类似牛顿迭代法的思路,效率还是蛮不错的。


无论你是在校学生,还是资深搬砖师,欢迎你加入:力扣神秘刷题交流群

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值