P8615 [蓝桥杯 2014 国 C] 拼接平方数——Java解答

P8615 蓝桥杯 2014 国 C 拼接平方数

题目描述

小明发现 49 49 49 很有趣,首先,它是个平方数。它可以拆分为 4 4 4 和 9 9 9,拆分出来的部分也是平方数。 169 169 169 也有这个性质,我们权且称它们为:拼接平方数。

100 100 100 可拆分 1 , 00 1,00 1,00,这有点勉强,我们规定, 0 , 00 , 000 0,00,000 0,00,000 等都不算平方数。

小明想:还有哪些数字是这样的呢?

你的任务出现了:找到某个区间的所有拼接平方数。

输入格式

两个正整数 a , b ( a < b < 1 0 6 ) a,b(a<b<10^6) a,b(a<b<106)。

输出格式

若干行,每行一个正整数。表示所有的区间 a , b a,b a,b 中的拼接平方数,从小到大输出。

输入输出样例 #1

输入 #1

复制代码
169 10000

输出 #1

复制代码
169
361
1225
1444
1681
3249
4225
4900
9025

说明/提示

时限 1 秒, 256M。蓝桥杯 2014 年第五届国赛
洛谷链接

思路讲解

先保证自己是平方数,再尝试所有"断位"拆法,看能不能拆出两个非零平方数。

java 复制代码
import java.util.Scanner;

public class Main {

    // 判断是不是平方数
    public static boolean isPerfectSquare(int n) {
        if (n < 0) {
            return false;
        }
        int num = (int) Math.sqrt(n);
        return num * num == n;
    }

    // 拆分后各自判断是不是拼接平方数
    public static boolean couldFormSquare(int num) {
        if (isPerfectSquare(num)) {
            // 按 10/100/1000... 的位置拆分
            for (int i = 10; i < num; i *= 10) {
                int numRight = num % i;   // 右边部分
                int numLeft = num / i;    // 左边部分
                // 两边都非 0 且都是平方数即可返回 true
                if (numRight != 0 && numLeft != 0 && isPerfectSquare(numRight) && isPerfectSquare(numLeft)) {
                    return true;
                }
            }
            return false;
        }
        return false;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();
        // 遍历区间 [a, b] 并输出所有拼接平方数
        for (int n = a; n <= b; n++) {
            if (couldFormSquare(n)) {
                System.out.println(n);
            }
        }
    }
}

但是,这段代码还有些不足。isPerfectSquare 每轮都调用 Math.sqrt,在 1e6 范围里 不会超时,但可以提前打表,把 0‥1 000 000 里所有平方数 一次性标记出来,后面 O(1) 查询 即可,这样大幅提升了效率。

什么是打表?

打表其实就是 "先把答案算出来,存到数组里,用的时候直接查"

空间换时间

  1. 开一块布尔数组
java 复制代码
static boolean[] isSquare = new boolean[1_000_001];   // 索引 0..1 000 000
  1. 代码运行时,一次性把平方数全标成 true,存放于数组中
java 复制代码
static {                  // 静态代码块只执行一次
    for (int i = 0; (long) i * i <= 1_000_000; i++) {  // i*i 可能超 int,强转 long
        isSquare[i * i] = true;              
        // 把 0,1,4,9,16...1 000 000 全标 true
    }
}
  1. 以后任何地方想判断 n 是不是平方数,直接isSquaren查询,时间复杂度为O(1)
java 复制代码
if (isSquare[n]) { ... }   // O(1) 查询,不用再算 sqrt

完整代码如下:

java 复制代码
import java.util.Scanner;

public class Main1 {

    //可以提前打表,把 0‥1 000 000 里所有平方数 一次性标记出来,后面 O(1) 查询 即可。
    static boolean[] isSquare = new boolean[1_000_001];  
    static {
        for (int i = 0; (long) i * i <= 1_000_000; i++) {
            isSquare[i * i] = true;
        }
    }


    //拆分后各自判断是不是拼接平方数
    public static boolean couldFormSquare(int num) {
        if (isSquare[num]) {
            for (int i = 10; i < num; i *= 10) {
                int numRight = num % i;
                int numLeft = num / i;
                if (isSquare[numRight] && isSquare[numLeft] && numRight != 0 && numLeft != 0) {
                    return true;
                }
            }
            return false;
        }
        return false;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();
        for (int n = a; n <= b; n++) {
            if (couldFormSquare(n)) {
                System.out.println(n);
            }
        }
    }
}
相关推荐
秋天的怀念_David10 分钟前
算法一千零一夜 · 第二十八夜 注册
java·程序人生·算法
Java码农也是农13 分钟前
Spring 事务详解:@Transactional 如何生效、何时回滚、传播行为怎么选
java·spring boot·spring·事务
学长毕设1 小时前
基于SpringBoot的游乐园管理系统-附源码
java·spring boot·后端
SimonKing1 小时前
震惊:怎么回事,opencode一轮对话耗尽免费额度
java·后端·程序员
装不满的克莱因瓶1 小时前
【SpringAI Alibaba】ReactAgent响应SSE实时流式传输案例实战
java·人工智能·ai·sse·springai
杨凯凡2 小时前
Spring Boot 文件上传怎么做才安全?流式落盘、路径校验与数据库一致性实战
java·spring boot·文件上传·后端安全·数据库一致性
这个昵称不容易2 小时前
旅游管理系统的设计与实现(SpringBoot + MySQL + Vue 前后端分离)
java·springboot·毕设
Rain的Java大神之路2 小时前
LeetCode 37 解数独面试攻略:回溯 + 位掩码 + MRV,从暴力到毫秒级求解
java·后端·leetcode
希和20273 小时前
C语言程序设计题|有序数组插入数字冒泡排序
c语言·数据结构·算法
天天被压力3 小时前
【A股分钟级高频数据完全手册 #11】券商实时行情数据接口:实时交易(券商源)接入与字段
java·人工智能·python