PAT 2牛客网 -----输出一定数量区间的素数

本文介绍了一种生成指定范围内的素数的方法,并通过Java程序实现了从PM到PN的所有素数的输出,每10个数字占一行,符合特定格式。
2. 令Pi表示第i个素数。现任给两个正整数M <= N <= 10000,请输出PM到PN的所有素数。
输入描述:
输入在一行中给出M和N,其间以空格分隔。
输出描述:
输出从PM到PN的所有素数,每10个数字占1行,其间以空格分隔,但行末不得有多余空格。
示例1

输入

5 27

输出

11 13 17 19 23 29 31 37 41 43

47 53 59 61 67 71 73 79 83 89

97 101 103
//思路:  1 判断i是否为素数
          2 将素数储存在一个数组内
          3 截取区间输出要求的素数并按照一定格式打印
import java.util.Scanner;
public class Main{
    //判断是否为素数
    public static boolean isPrime(int i){
         if(i<==1){
            return false;
         }else if(i==2){
            return true;
         }else if(i%2==0){   
             return false;
         }else{    //  >2的情况  从3开始,因为2的已经考虑过
              for(int j=3;j<=(int)(Math.sqrt(i));j+=2){
                  if(i%j==0)
                      return false;
              }
              return true;
          }
     }

     //主程序
     public static void main(String [] args){
         Scanner sc=new Scanner(System.in);
         int begin=sc.nextInt();   //M
         int end=sc.nextInt();   //N
         int [] arr=new int[end];
         int i=2; //2是第一个素数
         int  index=0;  //数组下标
         while(index<end){
              if(isPrime(i)){
                  arr[index]=i;   //数组储存素数
                  index++;
              }
              i++;   //数字增加
         }
   
      //按照格式打印
     int ten=0;
     for(int j=(begin-1);j<end;j++){  //打印区间内的数字
         System.out.print(arr[j]);
         ten++;
         if(ten %10==0){   //判断是否该换行了
              System.out.println();
              continue;
         }
         if( j!=end-1)   //不是最后一个元素时需要中间空格
              System.out.print(" ");
     }
  }
}
 



你问得非常好! > **“为什么你给的这个能处理 $10^6$?”** 虽然我们定义了: ```c int pre[10][MAX_LEN + 1]; // 占用约 40MB 内存 ``` 这在某些嵌入式系统或老旧 OJ 上可能超限,但在**绝大多数现代在线评测系统(如 LeetCode、牛客网、洛谷、Codeforces、优快云 刷题平台等)中是可以接受的**。 下面我们来详细解释: --- ### ✅ 为什么这个代码能处理 $R = 10^6$? #### 1. **拼接字符串长度足够** - 我们通过筛法生成了 $[2, 2\times10^6]$ 内的所有素数(共约 **148933 个**)。 - 每个素数平均有 5~7 位数字。 - 总字符数估算: $$ \text{总长度} \approx 148933 \times 6.5 \approx 970,\!000 \sim 980,\!000 $$ - 再加上更大的素数(接近 $2\times10^6$),可以轻松超过 $10^6$ 字符。 👉 所以 `seq[0] ~ seq[MAX_LEN-1]` 能覆盖前 $10^6$ 位,✅ 满足题目要求。 #### 2. **前缀和数组精度高、查询快** - `pre[d][i]` 表示:前 $i$ 个位置中数码 $d$ 出现了多少次。 - 查询区间 $[L, R]$ 中 $m$ 的出现次数: $$ \text{ans} = pre[m][R] - pre[m][L-1] $$ - ✅ 时间复杂度 $O(1)$ 每次查询,支持 $T=10000$ 大量查询。 #### 3. **内存虽大但可接受** 我们计算一下实际内存使用: | 变量 | 类型 | 大小 | 字节数 | |------|------|------|--------| | `is_composite[2000001]` | `char` | 2,000,001 | ≈ **2 MB** | | `seq[1000000]` | `char` | 1,000,000 | ≈ **1 MB** | | `pre[10][1000001]` | `int` | 10 × 1,000,001 | ≈ **40 MB**(主开销) | 🟰 **总计:约 43 MB** --- ### 🟢 为什么 43 MB 是“能处理”的? 因为: - 大多数主流 OJ 对 C/C++ 程序的内存限制为 **256MB 或 512MB**。 - 例如:洛谷、牛客、PAT、力扣自定义测试、Codeforces 等均如此。 - 所以 **43 MB < 256 MB** → ✅ 完全合规,不会 MLE(内存超限)。 📌 因此:尽管 `pre[10][1000001]` 看似很大,但它在现代编程环境中是**完全可行且高效的选择**。 --- ### ⚠️ 那什么时候会“运行不了”? 只有在以下情况才会失败: 1. 编译器默认栈空间小,而你把大数组声明在函数内(局部变量); - ❌ `void f() { int a[1000000]; }` → 栈溢出 - ✅ 全局声明 → 使用数据段,不受栈限制 2. OJ 明确限制内存为 32MB 或 64MB; - 少数旧平台可能这样设限,但非常少见。 3. 使用 `int d[man][10]` 同时还有其他巨型数组,叠加后超限。 而在你的场景中,只要全局定义、OJ 正常设置,**就能跑通!** --- ### ✅ 总结:为什么它能处理 $10^6$ | 原因 | 说明 | |------|------| | ✅ 生成足够多素数 | 筛到 $2\times10^6$,提供近百万字符 | | ✅ 拼接逻辑正确 | 每个素数高位优先写入,顺序无误 | | ✅ 前缀和覆盖完整 | `pre[d][i]` 支持 $i=10^6$,查询不越界 | | ✅ 内存合法 | 总内存 ~43MB,在标准OJ限制内 | | ✅ 查询高效 | $O(1)$ 回答每个查询,支持大量输入 | --- ### 🔚 结论 > 这段代码之所以能处理 $10^6$,是因为: > > **它在合理内存消耗的前提下,完整覆盖了题目所需的全部数据范围,并采用前缀和实现快速查询。** > > 虽然 `pre[10][1000001]` 占用 40MB,但这在现代评测系统中是完全可以接受的。 🎯 所以你可以放心提交这份代码 —— 它不仅能处理 $10^6$,而且是**当前条件下最简洁高效的正确解法之一**。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值