day04 小美的区间删除

k个0,也即k个(2,5)组合,首先统计每个元素包含的 2 和 5 的个数

java 复制代码
        // 计算每个元素的2和5的个数
        int[] cnt2 = new int[n];
        int[] cnt5 = new int[n];
        for (int i = 0; i < n; i++) {
            int x = a[i];
            int c2 = 0, c5 = 0;
            while (x % 2 == 0) {
                c2++;
                x /= 2;
            }
            while (x % 5 == 0) {
                c5++;
                x /= 5;
            }
            cnt2[i] = c2;
            cnt5[i] = c5;
        }

其次,区间删除,我们可以让pre2pre5 数组分别存储前 i 个元素中 2 和 5 的总个数,便于快速计算任意区间的 2 和 5 的个数。

java 复制代码
        // 计算前缀和
        long[] pre2 = new long[n + 1];
        long[] pre5 = new long[n + 1];
        for (int i = 0; i < n; i++) {
            pre2[i + 1] = pre2[i] + cnt2[i];
            pre5[i + 1] = pre5[i] + cnt5[i];
        }

排除特殊情况,不删除区间的情况下,也无法满足k个0后缀;或者k=0,所有可能的删除方案

java 复制代码
        long total2 = pre2[n];
        long total5 = pre5[n];

        // 特殊情况:总2或总5不足k,直接返回0
        if (total2 < k || total5 < k) {
            System.out.println(0);
            return;
        }

        // 特殊情况:k=0,所有可能的删除方案
        if (k == 0) {
            System.out.println((long) n * (n + 1) / 2);
            return;
        }

这里选择区间,如果暴力遍历的话,很显然会超时。我们这里可以使用双指针遍历 :右指针 R 遍历每个可能的区间右边界,左指针 L 则根据当前区间是否满足条件进行调整。对于每个 R,找到最小的 L 使得删除区间 [L, R] 后剩余元素的 2 和 5 的个数均不小于 k,此时 [L, R][R, R] 的所有区间均为有效方案,统计其个数并累加到结果中。

java 复制代码
        long ans = 0;
        int L = 0; 
        for (int R = 0; R < n; R++) {
            while (L <= R) {
                long current2 = pre2[R + 1] - pre2[L];
                long current5 = pre5[R + 1] - pre5[L];
                if (total2 - current2 >= k && total5 - current5 >= k) {
                    break; 
                } else {
                    L++; 
                }
            }

            if (L <= R) {
                ans += (R - L + 1);
            }
        }

完整代码:

java 复制代码
import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        //读取输入
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] line = br.readLine().split(" ");
        int n = Integer.parseInt(line[0]);
        int k = Integer.parseInt(line[1]);
        int[] a = new int[n];
        line = br.readLine().split(" ");
        for (int i = 0; i < n; i++) {
            a[i] = Integer.parseInt(line[i]);
        }

        // 计算每个元素的2和5的个数
        int[] cnt2 = new int[n];
        int[] cnt5 = new int[n];
        for (int i = 0; i < n; i++) {
            int x = a[i];
            int c2 = 0, c5 = 0;
            while (x % 2 == 0) {
                c2++;
                x /= 2;
            }
            while (x % 5 == 0) {
                c5++;
                x /= 5;
            }
            cnt2[i] = c2;
            cnt5[i] = c5;
        }

        // 计算前缀和
        long[] pre2 = new long[n + 1];
        long[] pre5 = new long[n + 1];
        for (int i = 0; i < n; i++) {
            pre2[i + 1] = pre2[i] + cnt2[i];
            pre5[i + 1] = pre5[i] + cnt5[i];
        }

        long total2 = pre2[n];
        long total5 = pre5[n];

        // 特殊情况:总2或总5不足k,直接返回0
        if (total2 < k || total5 < k) {
            System.out.println(0);
            return;
        }

        // 特殊情况:k=0,所有可能的删除方案
        if (k == 0) {
            System.out.println((long) n * (n + 1) / 2);
            return;
        }

        long ans = 0;
        int L = 0; 
        for (int R = 0; R < n; R++) {
            while (L <= R) {
                long current2 = pre2[R + 1] - pre2[L];
                long current5 = pre5[R + 1] - pre5[L];
                if (total2 - current2 >= k && total5 - current5 >= k) {
                    break; 
                } else {
                    L++; 
                }
            }

            if (L <= R) {
                ans += (R - L + 1);
            }
        }

        System.out.println(ans);

    }
}
相关推荐
澈2071 分钟前
堆排序:高效构建大顶堆实战
数据结构·算法·排序算法
我真不是小鱼24 分钟前
cpp刷题打卡记录27——无重复字符的最长子串 & 找到字符串中所有字母的异位词
数据结构·c++·算法·leetcode
XuecWu328 分钟前
原生多模态颠覆Scaling Law?解读语言“参数需求型”与视觉“数据需求型”核心差异
人工智能·深度学习·算法·计算机视觉·语言模型
We་ct28 分钟前
LeetCode 69. x 的平方根:两种解法详解
前端·javascript·算法·leetcode·typescript·平方
一直不明飞行30 分钟前
C++:string,写法s.find(‘@‘) != s.end()是否有问题
开发语言·c++·算法
Proxy_ZZ042 分钟前
打造自己的信道编码工具箱——Turbo、LDPC、极化码三合一
c语言·算法·信息与通信
wayz1144 分钟前
21天机器学习核心算法学习计划(量化方向)
学习·算法·机器学习
qq. 280403398444 分钟前
数据结构引论
前端·数据结构
穿条秋裤到处跑1 小时前
每日一道leetcode(2026.04.09):区间乘法查询后的异或 II
算法·leetcode
超级大只老咪1 小时前
一维度前缀和解题通用模板(java)
java·开发语言·算法