And echoed in the wells of silence.|

MessageBoxA

园龄:4年9个月粉丝:4关注:0

2024-05-10 00:16阅读: 12评论: 0推荐: 0

NOI模拟 刀客球

涉及知识点:数论,单调栈

题意

给你一串长度为 n (105) 的序列,值域 107,求该序列所有区间的 lcm 之积,对 109+7 取模。

思路

形如求 “所有区间” 的某种值的这种题目,肯定不能直接直接思考每个区间的贡献,因为但就枚举区间的基本复杂度 O(n2) 是很难降下来的,一般这种情况有两种解决方式:

  1. O(n) 顺序遍历所有点,对于节点 i 可以在 O(logn) 或者 O(n) 的复杂度之内求出以 i 结尾的所有区间的贡献。
  2. O(n) 遍历所有节点,并且可以快速计算出节点 i 决定了哪些节点的贡献。本题采用的是这种做法。

首先考虑如何计算一个区间的 lcm,直接利用 lcm(a,b,c)=lcm(lcm(a,b),c) 是不现实的,不同于 gcd 会越操作越小,这样计算 lcm 会导致非常大的结果。但还有另外一种计算方式,即我们将每个数质因数分解,然后将每个质因数的次方数取区间最大值,最后相乘即可得到区间 lcm,形式化地说,设 ai=p1q1p2q2pkqk,那么区间 al,,ar 的区间 lcm 即为 p1maxi=lrqip2maxi=lrqi pkmaxi=lrqi

于是我们想到可以分开计算每个质因数的贡献,对于第 i 个数 ai 的第 j 个质因数 pi,j,记 ai 分解后 pi,j 上的指数为 qi,jpi,j 做出的贡献即为 ai 往左往右拓展直到某个数质因数分解后 pi,j 的指数大于 qi,j,形式化的讲,找到一个极大的区间 [l,r] 使得 t[l,r],at=p1q1p2q2pkqk,如果有 px=pi,j,满足 qxqi,j(两边都取小于等于可能会导致重复计数,所以在实现时要左闭右开)。

实现

为了常数更优,我们将分解出的质因数分成两部分计算,以 值域 为分界线,大于此分界线的质因数在每个数中最多出现 1 次,上文所述的”能拓展的区间“很显然就是左边第一个与右边第一个含有相同质因子的数,但是由于统计时”左开右闭“(代码里是左开右闭方便写,左闭右开也行),实际上计数时右端点是序列尾端点;而小于等于分界线的数通过单调栈实现 O(n)​ 找左右能拓展的最远点。

代码

#include<bits/stdc++.h>
using namespace std;
#ifdef ONLINE_JUDGE
#define getchar __getchar
inline char __getchar(){
    static char ch[1<<20],*l,*r;
    return (l==r&&(r=(l=ch)+fread(ch,1,1<<20,stdin),l==r))?EOF:*l++;
}
#endif
template<class T>inline void rd(T &x){
    T res=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while('0'<=ch && ch<='9'){res=res*10+ch-'0';ch=getchar();}
    x=res*f;
}
template<class T>inline void wt(T x,char endch='\0'){
    static char wtbuff[20];
    static int wtptr;
    if(x==0){
        putchar('0');
    }
    else{
        if(x<0){x=-x;putchar('-');}
        wtptr=0;
        while(x){wtbuff[wtptr++]=x%10+'0';x/=10;}
        while(wtptr--) putchar(wtbuff[wtptr]);
    }
    if(endch!='\0') putchar(endch);
}
typedef long long LL;
const LL P=1e9+7;
const int MAXN=100005,MAXA=1e7;
int n,pre[MAXN],aft[MAXN],cnt[MAXN];
LL a[MAXN],ans=1;
inline LL qpow(LL x,LL y){
    x%=P;
    LL res=1;
    while(y){
        if(y&1) res=res*x%P;
        x=x*x%P;
        y>>=1;
    }
    return res;
}
int pri[MAXA],pri_cnt=0;
bool vis[MAXA+5];
inline void get_prime(){
    for(int i=2;i<=MAXA;i++){
        if(!vis[i]) pri[++pri_cnt]=i;
        for(int j=1;j<=pri_cnt;j++){
            if(1LL*pri[j]*i>MAXA) break;
            vis[pri[j]*i]=1;
            if(i%pri[j]==0) break;
        }
    }
}
int stk[MAXN],stp;
pair<int,int>tot[MAXN];
int totcnt=0;
int main(){

    get_prime();

    rd(n);
    for(int i=1;i<=n;i++){
        rd(a[i]);
    }

    for(int j=1;1LL*pri[j]*pri[j]<=MAXA;j++){
        int it=pri[j];
        for(int i=1;i<=n;i++){
            cnt[i]=0;
            while(a[i]%it==0){
                a[i]/=it;
                cnt[i]++;
            }
        }

        stp=1;
        stk[1]=0;
        cnt[0]=0x3f3f3f3f;
        for(int i=1;i<=n;i++){
            while((stp) && (cnt[i]>cnt[stk[stp]])) stp--;
            pre[i]=stk[stp];stk[++stp]=i;
        }

        stp=1;
        stk[1]=n+1;
        cnt[n+1]=0x3f3f3f3f;
        for(int i=n;i>=1;i--){
            while((stp) && (cnt[i]>=cnt[stk[stp]])) stp--;
            aft[i]=stk[stp];stk[++stp]=i;
        }
        for(int i=1;i<=n;i++){
            ans=ans*qpow(it,1LL*cnt[i]*(i-pre[i])*(aft[i]-i))%P;
        }
    }

    for(int i=1;i<=n;i++){
        if(a[i]>1) tot[++totcnt]=make_pair(a[i],i);
    }
    sort(tot+1,tot+1+totcnt);
    for(int l=1,r,lst;l<=totcnt;){
        r=l;
        while(r+1<=totcnt && tot[l].first==tot[r+1].first) r++;
        lst=0;
        for(int i=l;i<=r;i++){
            ans=ans*qpow(tot[i].first,1LL*(tot[i].second-lst)*(n-tot[i].second+1))%P;
            lst=tot[i].second;
        }
        l=r+1;
    }

    wt(ans,'\n');
    return 0;
}

处理小于分界线的数的循环:

枚举质因数 O(R),分解质因数 O(logn),单调栈 O(n),综合最大复杂度 O(nR)R 为值域

处理大于分界线的数的循环:

双指针,O(n)

本文作者:MessageBoxA

本文链接:https://www.cnblogs.com/SkyNet-PKN/p/18183375

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   MessageBoxA  阅读(12)  评论(0编辑  收藏  举报
历史上的今天:
2023-05-10 USACO23FEB-Gold/洛谷P9127 Equal Sum Subarrays
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 evening Corn Wave
  2. 2 Группа крови Кино
  3. 3 The Sound Of Silence Simon & Garfunkel
  4. 4 dB doll YUE.STEVEN
dB doll - YUE.STEVEN
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.