分解质因数,发现一个子区间内要保持互质关系才能满足 乘积==lcm
贪心思想找到当前点最远能到的点,此处可以用双指针
倍增优化查询时跳的速度。
#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位 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; }
原文:https://www.cnblogs.com/PdrEam/p/14695577.html