5023. Squence

题目大意

给定一个长度为 n 的序列A,有 m 个询问,每次询问[l,r],求

i=lrj=lrω(gcd(Ai,Aj))

ω(x) x 不同质因子的个数。

Data Constraint
n,m100000,Ai10000000

题解

AI 不同的质因子很少,所以直接莫队,维护一个桶即可。

时间复杂度: O(nn)

SRC

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std ;

#define N 10000000 + 10
#define M 100000 + 10
#define Max( a , b ) ( a > b ? a : b )
typedef long long ll ;
struct Query {
    int l , r , h ;
} Q[M] ;

vector < int > Que[M] ;

int flag[N] , T[10*M] ;
int Pri[N] , P[N] ;
int A[M] , Belong[M] ;
int n , m , Maxv , Block , Cnt ;
ll Ans[M] , nowans ;

inline int Read() {
    int ret = 0 ;
    char ch = getchar() ;
    while ( ch < '0' || ch > '9' ) ch = getchar() ;
    while ( ch >= '0' && ch <= '9' ) {
        ret = ret * 10 + ch - '0' ;
        ch = getchar() ;
    }
    return ret ;
}

inline void Pre() {
    for (int i = 2 ; i <= Maxv  ; i ++ ) {
        if ( !flag[i] ) {
            Pri[++Pri[0]] = i ;
            P[i] = i ;
        }
        for (int j = 1 ; j <= Pri[0] ; j ++ ) {
            if ( 1ll * i * Pri[j] > Maxv ) break ;
            flag[i*Pri[j]] = 1 ;
            P[i*Pri[j]] = Pri[j] ;
            if ( i % Pri[j] == 0 ) break ;
        }
    }
}

inline bool cmp( Query a , Query b ) { return Belong[a.l] < Belong[b.l] || ( Belong[a.l] == Belong[b.l] && a.r < b.r ) ; }

inline void Modify( int l , int r , int del ) {
    for (int i = l ; i <= r ; i ++ ) {
        int siz = Que[i].size() ;
        for (int j = 0 ; j < siz ; j ++ ) {
            int now = Que[i][j] ;
            nowans = nowans - 1ll * T[now] * T[now] + 1ll * (T[now] + del) * (T[now] + del) ;
            T[now] += del ;
        }
    }
}

int main() {
    freopen( "sequence.in" , "r" , stdin ) ;
    freopen( "sequence.out" , "w" , stdout ) ;
    memset( flag , 0 , sizeof(flag) ) ;
    n = Read() , m = Read() ;
    Block = n > 50000 ? 600 : 400 ;//sqrt(n) ;
    for (int i = 1 ; i <= n ; i ++ ) A[i] = Read() , Maxv = Max( Maxv , A[i] ) ;
    Pre() ;
    for (int i = 1 ; i <= n ; i ++ ) {
        Belong[i] = i / Block + (i % Block != 0) ;
        int x = A[i] ;
        while ( x > 1 ) {
            int now = P[x] ;
            if ( !flag[now] ) flag[now] = ++ Cnt ;
            while ( x % now == 0 ) x /= now ;
            Que[i].push_back( flag[now] ) ;
        }
    }
    for (int i = 1 ; i <= m ; i ++ ) {
        Q[i].l = Read() , Q[i].r = Read() ;
        Q[i].h = i ;
    }
    sort( Q + 1 , Q + m + 1 , cmp ) ;
    Modify( Q[1].l , Q[1].r , 1 ) ;
    Ans[Q[1].h] = nowans ;
    int lasl = Q[1].l , lasr = Q[1].r ;
    for (int i = 2 ; i <= m ; i ++ ) {
        if ( lasl < Q[i].l ) Modify( lasl , Q[i].l - 1 , -1 ) ;
        if ( lasr > Q[i].r ) Modify( Q[i].r + 1 , lasr , -1 ) ;
        if ( lasl > Q[i].l ) Modify( Q[i].l , lasl - 1 , 1 ) ;
        if ( lasr < Q[i].r ) Modify( lasr + 1 , Q[i].r , 1 ) ;
        Ans[Q[i].h] = nowans ;
        lasl = Q[i].l , lasr = Q[i].r ;
    }
    for (int i = 1 ; i <= m ; i ++ ) printf( "%lld\n" , Ans[i] ) ;
    return 0 ;
}

以上.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值