Sequence

题目大意

若干个区间询问
每次询问 ri=lrj=lw((ai,aj))
w(x)表示x的不同质因子数。

以根号n为阈值,用两种算法。
小于等于根号n的质数枚举+前缀和
大于根号n的就上莫队
当然直接莫队也能 8nn

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=100000+10,maxd=10000000+10,B=700,wys=3;
struct dong{
    int l,r,id;
} ask[maxn];
ll ans[maxn];
int belong[maxn],c[maxd],cnt[maxn],fj[maxn][15];
int a[maxn],f[maxd],g[maxd],pri[maxd],sta[80];
bool bz[maxd];
int i,j,k,l,r,t,n,m,tot,top;
ll now;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
inline bool cmp(dong a,dong b){
    return belong[a.l]<belong[b.l]||belong[a.l]==belong[b.l]&&a.r<b.r;
}
inline void ins(int p){
    int i,j;
    fo(i,1,cnt[p]){
        j=fj[p][i];
        now+=(ll)2*c[j]+1;
        c[j]++;
    }
}
inline void del(int p){
    int i,j;
    fo(i,1,cnt[p]){
        j=fj[p][i];
        c[j]--;
        now-=(ll)2*c[j]+1;
    }
}
/*inline void ins(int p){
    int i,j,t=cnt[p];
    ll n1=0,n2=0,n3=0;
    for(i=1;i<=t;i+=wys){
        j=fj[p][i];
        n1+=(ll)2*c[j]+1;
        c[j]++;
        j=fj[p][i+1];
        if (j){
            n2+=(ll)2*c[j]+1;
            c[j]++;
            j=fj[p][i+2];
            if (j){
                n3+=(ll)2*c[j]+1;
                c[j]++;
            }
        }
    }
    now+=n1+n2+n3;
}
inline void del(int p){
    int i,j,t=cnt[p];
    ll n1=0,n2=0,n3=0;
    for(i=1;i<=t;i+=wys){
        j=fj[p][i];
        n1+=(ll)2*c[j]+1;
        c[j]++;
        j=fj[p][i+1];
        if (j){
            n2+=(ll)2*c[j]+1;
            c[j]++;
            j=fj[p][i+2];
            if (j){
                n3+=(ll)2*c[j]+1;
                c[j]++;
            }
        }
    }
    now-=n1+n2+n3;
}*/
inline void write(ll x){
    if (!x){
        putchar('0');
        putchar('\n');
        return;
    }
    top=0;
    while (x){
        sta[++top]=x%10;
        x/=10;
    }
    while (top) putchar('0'+sta[top--]);
    putchar('\n');
}
int main(){
    freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);
    fo(i,2,maxd-10){
        if (!bz[i]) pri[++top]=i,f[i]=g[i]=i;
        fo(j,1,top){
            if ((ll)i*pri[j]>maxd-10) break;
            bz[i*pri[j]]=1;
            f[i*pri[j]]=pri[j];
            if (i%pri[j]==0){
                g[i*pri[j]]=g[i]*pri[j];
                break;
            }
            g[i*pri[j]]=pri[j];
        }
    }
    n=read();m=read();
    fo(i,1,n) a[i]=read();
    fo(i,1,n){
        k=a[i];j=1;
        while (k>1){
            fj[i][++cnt[i]]=f[k];
            k/=g[k];
        }
    }
    fo(i,1,n) belong[i]=(i-1)/B+1;
    fo(i,1,m) ask[i].l=read(),ask[i].r=read(),ask[i].id=i;
    sort(ask+1,ask+m+1,cmp);
    l=1;r=0;
    fo(i,1,m){
        while (l<ask[i].l) del(l++);
        while (l>ask[i].l) ins(--l);
        while (r<ask[i].r) ins(++r);
        while (r>ask[i].r) del(r--);
        ans[ask[i].id]=now;
    }
    fo(i,1,m) write(ans[i]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值