https://codeforces.com/problemset/problem/920/F

题解:

线性筛+线段树+因子个数

先用素数线性筛筛选出因子个数

线段树维护

参考文章:https://blog.csdn.net/weixin_43272781/article/details/85058735

/*
*@Author:   STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>
//#define DEBUG
#define RI register int
using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=300000+10;
const int M=1000000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-8;
const int INF = 0x3f3f3f3f;
int t,n,m,k,q;
int ans,cnt,flag,temp;
int D[M];
int pre[M];
bool prime[M];
ll tree[N<<2];
bool skip[N<<2];
void pushup(int rt){
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
    skip[rt]=skip[rt<<1]&&skip[rt<<1|1];
}
void build(int l,int r,int rt){
    if(l==r){
        scanf("%d",&tree[rt]);
        if(tree[rt]<=2)
            skip[rt]=1;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    pushup(rt);

}
void updata(int l,int r,int rt,int L,int R){
    if(skip[rt])
        return;
    //cout<<rt;
    if(l==r){
        tree[rt]=D[tree[rt]];
        if(tree[rt]<=2)
            skip[rt]=1;
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid)updata(l,mid,rt<<1,L,R);
    if(R>mid)updata(mid+1,r,rt<<1|1,L,R);
    pushup(rt);
}
ll query(int l,int r,int rt,int L,int R){
    if(l>=L&&r<=R){
        return tree[rt];
    }
    int mid=(l+r)>>1;
    ll res=0;
    if(L<=mid)res+=query(l,mid,rt<<1,L,R);
    if(R>mid)res+=query(mid+1,r,rt<<1|1,L,R);
    return res;
}
char str;
int main()
{
#ifdef DEBUG
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif

    D[1]=1;
    prime[0]=prime[1]=1;
    for(int i=2;i<M;i++){
        if(!prime[i]){
            D[i]=2;
            pre[++cnt]=i;
        }
        for(int j=1;j<=cnt&&i*pre[j]<M;j++){
            prime[i*pre[j]]=1;
            D[i*pre[j]]=D[i]*2;
            if(i%pre[j]==0){
                int c=1;
                t=i;
                while(t%pre[j]==0){
                    t/=pre[j];
                    c++;
                }
                D[i*pre[j]]=D[t]*(c+1);
                break;
            }
        }
        //cout<<i<<" "<<D[i]<<endl;
    }
    scanf("%d%d",&n,&m);
    build(1,n,1);
    int l,r;
    while(m--){
        scanf("%d%d%d",&t,&l,&r);
        if(t==1){
            updata(1,n,1,l,r);
        }else{
            cout<<query(1,n,1,l,r)<<endl;
        }
    }


    //cout << "Hello world!" << endl;
    return 0;
}