1 ~ n 中有多少数可以表示为大于等于 K 的质数的乘积

链接:https://ac.nowcoder.com/acm/contest/11216/G
来源:牛客网

痛定思痛,奋楫争先再出发……
q 次询问。每次询问给定 n 和 K,问 1 ~ n 中有多少数可以表示为大于等于 K 的质数的乘积(一个数可以乘多次)。

输入描述:

链接:https://ac.nowcoder.com/acm/contest/11216/G
来源:牛客网

第一行读入一个整数q 
接下来q行每行读入2个整数,第i行表示 nin_iniKiK_iKi
1≤q≤3e61 \leq q\le 3e61q3e6,1≤ni,Ki≤3e61 \leq n_i,K_i\le 3e61niKi3e6。

输出描述:

q行,共 q 个数,分别表示 q 次询问的答案。
示例1

输入

复制 
1
100 5

输出

复制 
32
示例2

输入

复制
2
20 3
10 5

输出

复制
9
2


转化题意,会发现求的就是数的最小质因子大于等于 KK 的数个数。

开一个树状数组,从小到大,加入每个数的最小质因子。将询问挂在 nn 上,查询即可。

 

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=3e6+100;
int p[maxn];
int vis[maxn];
int z[maxn];
int cnt=0;
int c[maxn],ans[maxn];
int lowbit(int x){
    return x&-x;
}
struct node{
    int n,k;
    int id;
    bool  friend operator<(node a,node b){
        return a.n<b.n;
    }
}save[maxn];
void get_prime(){
    for(int i=2;i<maxn;i++){
        if(!vis[i]){
            p[++cnt]=i;
            z[i]=i;
        }
        for(int j=1;j<=cnt&&i*p[j]<maxn;j++){
            vis[i*p[j]]=1;
            z[i*p[j]]=p[j];
            if(i%p[j]==0){
                break;
            }
        }
    }
}
void add(int x){
    for(int i=x;i<maxn;i+=lowbit(i)){
        c[i]+=1;
    }
}
int get(int x){
    int ans=0;
    for(int i=x;i>0;i-=lowbit(i)){
        ans+=c[i];
    }
    return ans;
}
int main(){
    get_prime();
    int m;
    cin>>m;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&save[i].n,&save[i].k);
        save[i].id=i;
    }
    sort(save+1,save+m+1);
    int l=1;
    for(int i=1;i<=m;i++){
        while(l<save[i].n){
            add(z[++l]);
        }
        ans[save[i].id]=save[i].n-1-get(save[i].k-1);
    }
    for(int i=1;i<=m;i++){
        cout<<ans[i]<<"\n";
    }
    
} 

 

posted @ 2021-11-14 23:38  lipu123  阅读(91)  评论(0)    收藏  举报