列表

详情


NC14833. 珂朵莉的约数

描述

珂朵莉给你一个长为n的序列,有m次查询

每次查询给两个数l,r

s为区间[l,r]内所有数的乘积

s的约数个数mod 1000000007

输入描述

第一行两个正整数n,m
第二行一个长为n的序列
之后m行每行两个数l和r

输出描述

对于每个询问,输出一个整数表示答案

示例1

输入:

5 5
64 2 18 9 100
1 5
2 4
2 3
1 4
3 4

输出:

165
15
9
45
10

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 606ms, 内存消耗: 74192K, 提交时间: 2022-03-10 15:47:42

#include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a),_en=(b);i<=_en;i++)
#define M 100005
#define mod 1000000007
using namespace std;
int a[M],y[M][170],n,m,S,l=1,r,res=1;
int ans[M],q[10*M],yz[M],cnt,ni[M];
bool mk[M];
struct name{
	int l,r,id;
	bool operator <(const name &_)const{
        if (l/S!=_.l/S) return l<_.l;
        if ((l/S)&1) return r>_.r;
        return r<_.r;
    }
}Q[M];
void init(){
    ni[1]=ni[0]=1;S=sqrt(n);
    For(i,2,1000){
        if(mk[i])continue;
        yz[cnt++]=i;
        for(int j=i*2;j<=1000;j+=i)mk[j]=1;
    }
    For(i,2,n)ni[i]=1ll*(mod-mod/i)*ni[mod%i]%mod;
}
void add(int x){
    if(a[x]==1)return;
    res=1ll*res*ni[q[a[x]]+1]%mod;
    q[a[x]]++;
    res=1ll*res*(q[a[x]]+1)%mod;
}
void del(int x){
    if(a[x]==1)return;
    res=1ll*res*ni[q[a[x]]+1]%mod;
    q[a[x]]--;
    res=1ll*res*(q[a[x]]+1)%mod;
}
int main(){
    scanf("%d%d",&n,&m);init();
    For(i,1,n){
		int x;
		scanf("%d",&x);
		For(j,0,167){
			y[i][j]+=y[i-1][j];
			while(!(x%yz[j])){
				x/=yz[j];
				y[i][j]++;
			}
		}
		a[i]=x;
	}
    For(i,1,m){
		scanf("%d%d",&Q[i].l,&Q[i].r);
		Q[i].id=i;
	}
    sort(Q+1,Q+m+1);
    For(i,1,m){
        while(l>Q[i].l)add(--l);
        while(r<Q[i].r)add(++r);
        while(l<Q[i].l)del(l++);
        while(r>Q[i].r)del(r--);
        int ANS=1;
        For(j,0,167)
            ANS=1ll*ANS*(y[r][j]-y[l-1][j]+1)%mod;
        ans[Q[i].id]=1ll*res*ANS%mod;
    }
    For(i,1,m)printf("%d\n",ans[i]);
    return 0;
}

上一题