D. Cut

分解质因数,发现一个子区间内要保持互质关系才能满足 乘积==lcm

贪心思想找到当前点最远能到的点,此处可以用双指针

倍增优化查询时跳的速度。

记录2的倍数次跳转后到达的位置达到log的复杂度

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const ll mod = 1e9+7;
const ll maxn = 2e5+10;
ll x,y,k,n,a[maxn],st[maxn][50];//记录当前位置实际跳转的+1位 第二位表示跳(1<<(j-1)次
ll cnt[maxn];//桶记录质数个数 
void q(){
    ll ans=0;
    cin>>x>>y;
    for(int i=30;i>=1;--i){
        if(st[x][i]<=y){//记录的是+1位,所以相等还没有到 
            ans=ans+(1ll<<(i-1));
            x=st[x][i];
        }
    }
    cout<<(ans+1)<<"\n";
}
void pop(int x){
    for(int i=2;i*i<=x;++i){
        while(x%i==0){
            x=x/i;
            cnt[i]--;
        }
    }
    if(x>1)    cnt[x]--;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>k;
    for(int i=1;i<=n;++i){
        cin>>a[i];
    }
    int p1=1,p2=1;//双指针贪心 
    while(p2<=n){
        int x=a[p2];
        for(int i=2;i*i<=x;++i){
            if(x%i==0){
                while(cnt[i]){//不满足互质关系 
                    st[p1][1]=p2;
                    pop(a[p1]);
                    p1++;
                }
                while(x%i==0){//加上当前质数 
                    x=x/i;
                    cnt[i]++;
                }
            }
        }
        if(x>1){
            while(cnt[x]){//不满足互质关系 
                st[p1][1]=p2;
                pop(a[p1]);
                p1++;
            }
            cnt[x]++;
        }
        p2++;
    }
    while(p1!=p2){//p2==n+1
        st[p1][1]=p2;p1++; 
    }
    for(int i=0;i<=30;++i){//界限位置怎么跳都是这样 
        st[n+1][i]=n+1;
    }
    for(int i=n;i>=1;--i){
        for(int j=2;j<=30;++j){
            ll nxt=min(n+1,st[i][j-1]);
            st[i][j]=st[nxt][j-1];
        }
    }
    for(int i=1;i<=k;++i)q(); 
    return 0;
}

 

posted @ 2021-04-23 21:14  PdrEam  阅读(153)  评论(0编辑  收藏  举报