选拔赛A题“一个部族,一个民族,一个弗雷尔卓德。”

在这里插入图片描述
在这里插入图片描述
这题就是一个素数筛再加上一个线段树。首先数据素数筛将每个最小素因子的倍数标记最小素因子(简单来讲就是把每个数最小素因子标记出来)然后再遍历每个数。线段树标记1-x-1中最小素因子小于当前最小素因子的数量。最后数组里就是1-x-1中符合标准的数字,最后输入再查询即可。这道题关键在于预先处理,处理好了这道题就很简单了。以下为A代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ffi;
const int maxn=1000005;
ffi node[maxn<<2];
ffi a[maxn],flag[maxn];
void pushup(int nd)
{
    node[nd]=node[nd<<1]+node[nd<<1|1];
}
void build(int l,int r,int nd)
{
    if(l==r)
    {node[nd]=0;
    return;}
    int mid=(l+r)>>1;
    build(l,mid,nd<<1);
    build(mid+1,r,nd<<1|1);
    pushup(nd);
}
void update(int pos,int l,int r,int nd)
{
    if(l==r)
    {
        node[nd]+=1;
        return;
    }
    int mid=(l+r)>>1;
    if(mid<pos)update(pos,mid+1,r,nd<<1|1);
    else update(pos,l,mid,nd<<1);
        pushup(nd);
}
ffi query(int s,int e,int l,int r,int nd)
{
    if(s<=l&&e>=r)
    {
        return node[nd];
    }
    ffi ans=0;
    int mid=(l+r)>>1;
    if(s<=mid)ans+=query(s,e,l,mid,nd<<1);
    if(e>mid)ans+=query(s,e,mid+1,r,nd<<1|1);
    return ans;
}
void getsum()
{
    build(1,maxn,1);
    update(1,1,maxn,1);
    memset(a,0,sizeof(a));
    memset(flag,0,sizeof(flag));
    for(ffi i=2;i<=sqrt(maxn);i++)
   {
        for(ffi j=i;j<maxn;j+=i)
            if(!flag[j])
            {a[j]=i;flag[j]=1;}
    }
    for(ffi i=2;i<maxn;i++)
        {if(a[i]==0)a[i]=i;
        ffi tep=a[i];
        a[i]=query(1,a[i],1,maxn,1);
        update(tep,1,maxn,1);}
}
int main()
{
    int t;scanf("%d",&t);
    getsum();
    while(t--)
    {
        ffi x;
        scanf("%lld",&x);
        printf("%lld\n",a[x]);
    }
}

以下为标准题解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值