You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Java实现整数N多进制前缀为1统计时循环异常排查

问题排查与代码修复

咱们先一步步拆解你代码里的问题,看看为什么只处理第一个测试用例就出异常了:

核心Bug分析

1. 原始输入n被意外修改

你在进制转换的内层while(temp>0)循环里,直接对输入的n做了除法和取余操作,把n改成了0。这就导致:

  • 第一个测试用例处理到后续进制j时,n已经是0,完全没法正确计算
  • 后续测试用例读取新的n后,同样会被这个循环修改成0,逻辑彻底混乱
    解决办法:用临时变量存储原始n,比如long temp = n;,只对temp做进制转换操作。

2. count变量未重置

你把count定义在所有测试用例循环外面,第一个测试用例的计数会累加到后面的测试用例里,导致结果完全错误。
解决办法:在每个测试用例开始时(也就是for循环内部)把count重置为0。

3. 最高位判断逻辑错误

你的代码里判断rem[1]==1,但rem数组存储的是从低位到高位的数字(比如6在2进制是110rem[0]是0,rem[1]是1,rem[2]是1)。正确的判断应该是检查最高位是否为1,也就是rem[index-1] == 1

4. 特殊情况未处理

  • N=1时,所有大于1的进制下,1的表示都是1,有无穷多进制,应该输出INFINITY
  • N=0时,所有进制下都是0,没有以1开头的情况,计数为0

修复后的基础代码(解决循环异常)

先解决循环异常的问题,代码如下:

import java.util.*;
public class MyClass {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        for(int i=0;i<t;i++) {
            long n = sc.nextLong(); // 用nextLong避免1e12的溢出问题
            long count = 0;
            
            // 处理特殊情况
            if(n == 1) {
                System.out.println("INFINITY");
                continue;
            }
            if(n == 0) {
                System.out.println(0);
                continue;
            }
            
            long j=2;
            while(j<=n) {
                long temp = n; // 用临时变量保护原始输入n
                int index=0;
                long[] rem = new long[60]; // 1e12在2进制最多40位,60足够
                while(temp>0) {
                    long rem1 = temp%j;
                    rem[index++] = rem1;
                    temp = temp / j;
                }
                // 检查最高位是否为1
                if(index > 0 && rem[index-1] == 1) {
                    count++;
                }
                j++;
            }
            System.out.println(count);
        }
        sc.close();
    }
}

效率优化(必做!否则大N会超时)

上面的代码虽然解决了循环异常,但当N达到1e12时,遍历从2到N的所有进制会直接超时(尤其是T=1e5的情况下)。我们可以用数学思路优化:

当N在b进制下以1开头,意味着存在整数k≥1,满足:
b^k ≤ N < 2*b^k

我们分两种情况统计:

  1. k=1:此时b的范围是floor(N/2)+1N,共有N - floor(N/2)个值
  2. k≥2:遍历k从2到log2(N)(最多40次,因为2^40≈1e12),对每个k计算b的上下界:(N/2)^(1/k) < b ≤ N^(1/k),统计其中的整数数量

优化后的高效代码

import java.util.*;
public class MyClass {
    public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        while(t-- >0) {
            long n = sc.nextLong();
            if(n == 1) {
                System.out.println("INFINITY");
                continue;
            }
            if(n == 0) {
                System.out.println(0);
                continue;
            }
            
            long count = 0;
            // 情况1:k=1,b的范围是 (n/2, n]
            count += n - (n/2);
            
            // 情况2:k≥2,遍历k直到high<2(b至少为2)
            for(int k=2; ;k++) {
                long low = (long)Math.pow(n/2.0, 1.0/k) + 1;
                long high = (long)Math.pow(n, 1.0/k);
                
                if(high < 2) break; // 没有符合条件的b,退出循环
                low = Math.max(low, 2); // 确保b不小于2
                
                if(low <= high) {
                    count += high - low + 1;
                }
            }
            System.out.println(count);
        }
        sc.close();
    }
}

这个代码的时间复杂度是O(T*logN),完全可以处理1e5个测试用例和1e12以内的N。

内容的提问来源于stack exchange,提问作者Virti Parekh

火山引擎 最新活动