XTU OJ 1279 Dual Prime

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

思路:一看就是要用前缀和,想到要如何标记呢,就用一个数组p[50000]来记录素数,用类似冒泡的方式,每个素数都会乘自己以外的其它素数,这样不就能生成全部的d_prime,就是注意要乘全,最小上界是2*p(大于500000的最小素数),判断用p[i]>1000000/p[j],防止溢出。

#include<stdio.h>
#include<string.h>
int prime[1000005]={1,1};// 用来搞埃筛 
int p[50000]={0};// 用来连续地记录数组 实践证明5e4个就行 
int nums[1000005]={0};// 用来搞前缀和 
int main()
{
    int cnt=0; // 记录p的长度 
    // 搞埃筛 
    for(int i=2;i<600000;i++){
        if(!prime[i]){
            for(int j=i*2;j<=1000001;j+=i){
                prime[j]=1;
            }
            p[cnt++]=i;
            if(i>500000) break;// 因为2*500000 = 1e6 超过我们的数据范围了 
        }
    }
    int t=0;
    for(int i=0;i<cnt;i++){
        for(int j=i+1;j<cnt-1;j++){// 是从i+1开始 因为n=p*q && p!=q 
            if(p[i]>1000000/p[j]) break; // 超出数据范围就break 不然等下会数组越界 
            nums[p[i]*p[j]]++; // 乘出来的合数就是目标合数 
        }
    }
    for(int i=1;i<=1000001;i++) nums[i]+=nums[i-1]; //前缀和 
    int K;
    scanf("%d",&K); 
    while(K--){
        int a,b;
        scanf("%d%d",&a,&b);
        printf("%d\n",nums[b]-nums[a-1]);
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值