Algo 1

分段打表即可。

Algo 2

o3-mini 给的分段筛:

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    long long l, r;
    cin >> l >> r;
    
    // 如果 r < 2 则没有素数
    if(r < 2){
        cout << 0;
        return 0;
    }
    
    // 预筛出 2 ~ sqrt(r) 的素数
    long long lim = static_cast<long long>(sqrt(r)) + 1;
    vector<bool> isPrime(lim + 1, true);
    isPrime[0] = isPrime[1] = false;
    for (int i = 2; i * i <= lim; i++){
        if(isPrime[i]){
            for (int j = i * i; j <= lim; j += i)
                isPrime[j] = false;
        }
    }
    vector<int> basePrimes;
    for (int i = 2; i <= lim; i++){
        if(isPrime[i])
            basePrimes.push_back(i);
    }
    
    // 分段筛: 每段的长度可以设为 10^6
    const int segmentSize = 1000000;
    long long ans = 0;
    for(long long low = l; low <= r; low += segmentSize){
        long long high = min(low + segmentSize - 1, r);
        vector<bool> mark(high - low + 1, true);
        
        // 对每个预筛的素数 p,在 [low, high] 上标记 p 的倍数
        for (int p : basePrimes) {
            // 找到 [low, high] 内 p 的第一个倍数
            long long start = max((long long)p * p, ((low + p - 1) / p) * p);
            for(long long j = start; j <= high; j += p){
                mark[j - low] = false;
            }
        }
        // 特殊处理 1 不是素数
        if(low == 1)
            mark[0] = false;
        
        // 统计满足条件的素数
        for(long long i = 0; i < mark.size(); i++){
            if(mark[i]){
                long long num = low + i;
                // 根据数论,素数可以表示为两个正整数平方和当且仅当
                // num == 2 或 num % 4 == 1
                if(num == 2 || num % 4 == 1)
                    ans++;
            }
        }
    }
    
    cout << ans;
    return 0;
}