XTU-OJ 1279-Dual Prime

题目描述

如果一个合数x=p⋅q,p,q是素数且p≠q,我们称x是双素数。 现给你一个区间[a,b],求区间内的的双素数个数。

输入

第一行是一个整数T(1≤T≤30000),为样例的数目。 以后每行一个样例,为两个整数a,b(1≤a≤b≤106)

输出

依次每行输出一个样例的结果。

样例输入

3
1 10
1 100
1 1000000

样例输出

2
30
209867

解题思路: 素数筛法 + 遍历 + 前缀和

先用素数筛 找到范围内的所有素数, 然后遍历素数集合,得到 Dual Prime(双素数),最后前缀和相加,得到双素数 前缀和数组。

AC代码(埃筛):

#include <stdio.h>

const int N = 1e6+5;
int prime[N] = {0};
int hesu[N]= {0};

int main()
{
    for (int i = 2; i*i <= N; i ++)             // 埃筛
        if (prime[i] == 0)
            for (int j = i*i; j <= N; j+=i)
                prime[j] = 1;
                
    for (int i = 2; i*i < N; i ++)              // 找到满足条件的 合数
        for (int j = i+1; i*j < N; j ++)
            if (prime[i] == 0 && prime[j] == 0)
                hesu[i*j] = 1;
                
    for (int i = 2; i <= N-5; i ++)             // 前缀和
        hesu[i] += hesu[i-1];
    int T;
    scanf("%d",&T);
    while ( T --)
    {
        int a,b;
        scanf("%d %d",&a,&b);
        printf("%d\n",hesu[b] - hesu[a-1]);
    }
    return 0;    
}

AC代码(欧筛):

#include <stdio.h>

const int MAXN = 1e6+5;
bool vis[MAXN+2];               // 筛选MAXN个素数
int prime[80000];               // 把素数依次存放在该数组中
int Dualprime[MAXN];

void isPrime()
{
    for (int i = 2; i < MAXN; i ++)
    {
        if ( !vis[i])
            prime[++prime[0]] = i;      // prime[0] --> 筛选出的素数个数
        for (int j = 1; j <= prime[0] && i <= MAXN/prime[j]; j ++)
        {
            vis[i*prime[j]] = 1;
            if (i % prime[j] == 0)
                break;
        }
    }
}
int main()
{
    isPrime();      // 欧筛

    for (int i = 1; prime[i]*prime[i] < MAXN; i ++)
        for (int j = i+1; prime[i]*prime[j] < MAXN; j ++)
            Dualprime[prime[i]*prime[j]] = 1;

    for (int i = 2; i <= MAXN-5; i ++)             // 前缀和
        Dualprime[i] += Dualprime[i-1];
    
    int T;
    scanf("%d",&T);
    while ( T --)
    {
        int a,b;
        scanf("%d %d",&a,&b);
        printf("%d\n",Dualprime[b] - Dualprime[a-1]);
    }
    return 0;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值