牛客练习赛9 F:珂朵莉的约数

题目传送门
参考博客:牛客练习赛9 F - 珂朵莉的约数

我和该博主一样的地方:写莫队的时候发现了曾经没有注意到的事情,就是要先进行add,然后进行delete。尴尬。。。

inv[0]=inv[1]==1,多写了一个等号,害我查了一天的bug,以为是莫队或者质因数分解写错了,一段一段的进行测试,发现都没错。。。可怕的等号。

代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=100000+100;
const int primax=1000000+100;
const ll mod=1000000007;

int prime[primax],invprime[primax],tot,mi[primax];
bool isprime[primax];
int inv[primax<<1];
int number[primax];
int b[maxn]; //保存超过1000的素因子 

int node[maxn][200];
int n,m;

struct Mo{

    int l,r;
    int id;
}mo[maxn];
int R[maxn];
bool cmp(Mo a,Mo b){

    return R[a.l]==R[b.l]?a.r<b.r:R[a.l]<R[b.l];
}

ll key;
ll Ans[maxn];

void init(){

    inv[0]=inv[1]=1;
    for(int i=2;i<(primax<<1);i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    for(int i=0;i<primax;i++) isprime[i]=true;
    isprime[0]=isprime[1]=false;
    tot=0;
    for(int i=2;i<primax;i++){

        if(isprime[i]) invprime[i]=tot,prime[tot++]=i,mi[i]=i;
        for(int j=0;j<tot && i*prime[j]<primax;j++){

            isprime[i*prime[j]]=false;
            mi[i*prime[j]]=mi[i];
            if(!(i%prime[j])) break;
        }
    }
}

inline void kaven(int pri,int v){

    if(pri==0) return ;
    key=key*inv[number[pri]+1]%mod;
    number[pri]+=v;
    key=key*(number[pri]+1)%mod;
}

int main(){

    init();
    scanf("%d%d",&n,&m); 
    int size=sqrt(1.0*n);
    for(int i=1;i<=n;i++) R[i]=i/size;
    for(int i=1;i<=n;i++){

        int tmp;
        scanf("%d",&tmp);
        if(mi[tmp]>1000) b[i]=mi[tmp],tmp/=mi[tmp];
        while(tmp>1){

            int t=mi[tmp];
            int c=0;
            while(tmp%t==0) c++,tmp/=t;
            node[i][invprime[t]]=c;
        }
    }
    for(int i=2;i<=n;i++){

        for(int j=0;j<200;j++) node[i][j]+=node[i-1][j];
    }
    for(int i=1;i<=m;i++){

        scanf("%d%d",&mo[i].l,&mo[i].r);
        mo[i].id=i;
    }
    sort(mo+1,mo+1+m,cmp);
    int l=1,r=0;
    key=1;
    for(int i=1;i<=m;i++){

        while(l>mo[i].l) kaven(b[l-1],1),l--;
        while(r<mo[i].r) kaven(b[r+1],1),r++;
        while(r>mo[i].r) kaven(b[r],-1),r--;
        while(l<mo[i].l) kaven(b[l],-1),l++;

        ll tmp=1;
        for(int j=0;j<200;j++){

            ll Add=1+node[mo[i].r][j]-node[mo[i].l-1][j];
            tmp=tmp*Add%mod;
        }
        Ans[mo[i].id]=key*tmp%mod;
    }
    for(int i=1;i<=m;i++) printf("%lld\n",Ans[i]);
}

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/81333877