珂朵莉的约数(牛客练习赛9)

链接:https://www.nowcoder.com/acm/contest/40/F
来源:牛客网

珂朵莉给你一个长为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

备注:

对于100%的数据,有n , m <= 100000 , a[i] <= 1000000


题解:对于1 - 1e6 范围的数他大于1e3的素数因子最多只有一个,我们可以用莫队来维护他,但对于1 - 1e3的来说最多有168个素数因子,所以用一个前缀和,来解决

调了一天的莫队,wawawawa 很迷茫,然后将那4个while 顺序转换一下,然后就A了。。。。。。。。(真是搞不清楚为啥会 Wa)

AC code:
#include <bits/stdc++.h>
   
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int MOD = 1e9+7;
  
int prime[1007],tot;bool vis[1007];
ll inv[N],ans[N],ant;
int Be[N],a[N],sum[N*10],pre[N][170]; // sum存 在区间内 > 1000 的素数的个数
void init()
{
    tot = 0;
    for(int i = 2;i <= 1000;i++)
    {
        if(vis[i])  continue;
        prime[tot++] = i;
        for(int j = i + i; j <= 1000; j += i )
            vis[j] = 1;
    }
}
   
struct Mo{
    int l,r,id;
}Q[N];
int cmp(Mo a,Mo b){ return Be[a.l] == Be[b.l] ? a.r < b.r : a.l < b.l;}
   
void add(int pos)
{
    if(a[pos] == 1) return;
    ant = ant*inv[1+sum[a[pos]]]%MOD;
    sum[a[pos]]++;
    ant = ant*(1+sum[a[pos]])%MOD;
}
void del(int pos)
{
    if(a[pos] == 1) return;
    ant = ant*inv[1+sum[a[pos]]]%MOD;
    sum[a[pos]]--;
    ant = ant*(1+sum[a[pos]])%MOD;
}
int main()
{
    int n,m;
    init();
    scanf("%d%d",&n,&m);
    inv[0] = inv[1] = 1; for(int i=2;i<=n+1;i++) inv[i]=1ll*(MOD-MOD/i)*inv[MOD%i]%MOD ;  // 逆元筛
    int len = sqrt(n);
    for(int i = 1;i <= n;i++)
    {
        scanf("%d",&a[i]);
        Be[i] = i/len;
        for(int j = 0;j < tot;j++)
        {
            pre[i][j] = pre[i-1][j];
            while(a[i] % prime[j] == 0)
            {
                pre[i][j]++;
                a[i] /= prime[j];
            }
        }
    }
    for(int i = 1;i <= m;i++)   scanf("%d%d",&Q[i].l,&Q[i].r),Q[i].id = i;
    sort(Q+1,Q+m+1,cmp);
    memset(sum,0,sizeof(sum));
    ant = 1;
    int l = 1,r = 0;
    for(int i = 1;i <= m;i++)
    {
        while(r < Q[i].r)   add(r+1),r++;
        while(r > Q[i].r)   del(r),r--;
        while(l < Q[i].l)   del(l),l++;
        while(l > Q[i].l)   add(l-1),l--;
        ll res = 1;
        for(int j=0;j<tot;j++)
            res=1ll*res*(pre[r][j]-pre[l-1][j]+1)%MOD;
        ans[Q[i].id] = 1ll*ant*res %MOD;
    }
    for(int i = 1;i <= m;i++)
        printf("%lld\n",ans[i]);
    return 0;
}

 




posted @ 2018-08-10 09:26  jadelemon  阅读(236)  评论(0编辑  收藏  举报