Be Geeks!

Subject:
https://ac.nowcoder.com/acm/contest/7817/B

Give you nnn个数,设 G ( i , j ) = g c d ( a i , a i + 1 . . . a j ) G(i,j)=gcd(a_i,a_{i+1}...a_j) G(i,j)=gcd(ai,ai+1...aj) M ( i , j ) = m a x ( a i , a i + 1 . . . a j ) M(i,j)=max(a_i,a_{i+1}...a_j) M(i,j)=max(ai,ai+1...aj),计算
∑ 1 ≤ i ≤ j ≤ n G ( i , j ) ⋅ M ( i , j ) \sum_{1\le i\le j\le n}G(i,j)\cdot M(i,j) 1ijnG(i,j)M(i,j)

Idea:
There are two problems to be solved here, one is the interval gcd gcdg c d , one is the sum of interval maximum values.

  • First for gcd gcdFor g c d , it can benlogm nlog^mn l o gm , preprocessed,mmm a i a_i aiThe maximum value. Assuming that the right endpoint is determined, the more the left endpoint goes to the left gcd gcdg c d is not strictly decreasing, if it decreases every time it is divided by at least2 22 , sogcd gcdThe number of g c d islog logl o g level. So the interval can then passdp dpd p preprocessed eachgcd gcdThe leftmost endpoint of g c d .
  • Interval gcd gcdAfter g c d is preprocessed, enumerate the right endpointiii , and then enumerate eachgcd gcdthe leftmost end pointjj of g c dj , assuming the last left endpoint iskkk , what we want to calculate is
    ∑ l = jk − 1 G (l, i) ⋅ M (l, i) \sum_{l=j}^{k-1}G(l,i)\cdot M(l ,i)l = jk1G(l,i)M(l,i)
    G ( l , i ) G(l,i) G(l,i ) are all the same. Now we need to calculate the sum of the maximum value. A prefix sum can be preprocessed. This prefix sum is based oniii is the longest increasing sequence from the right end to the left, and the contribution of each position is the distance between the value at this position and the first value greater than it on the left. Then mess around with calculations.
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
const int N=200009;
struct node {
    
    
    int l;
    ll val;
    node(int x,ll y):l(x),val(y) {
    
    }
};
int n,dp[N];
ll a[N],sum[N],ans=0;
vector<node>w[N];

namespace ST {
    
    
int a[N],n,dp[N][25],index[N][25],mm[N];//mm:logn/log2
void ST() {
    
    
    mm[0]=-1;
    for(int i=1; i<=n; ++i) {
    
    
        dp[i][0]=a[i];
        index[i][0]=i;

        mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
    }
    for(int j=1; j<=mm[n]; ++j)
        for(int i=1; (i+(1<<j)-1)<=n; ++i) {
    
    
            dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
            if(dp[i][j-1]<=dp[i+(1<<(j-1))][j-1]) {
    
    
                index[i][j]=index[i+(1<<(j-1))][j-1];
            } else {
    
    
                index[i][j]=index[i][j-1];
            }
        }

}
int query(int x,int y) {
    
    
    int t=mm[y-x+1];
    //return max(dp[x][t],dp[y-(1<<t)+1][t]);
    if(dp[x][t]<=dp[y-(1<<t)+1][t])
        return index[y-(1<<t)+1][t];
    else return index[x][t];
}
}



int main() {
    
    
    scanf("%d",&n);
    ST::n=n;
    for(int i=1; i<=n; i++)
        scanf("%lld",&a[i]),ST::a[i]=a[i];
    ST::ST();
    a[0]=mod;
    for(int i=1; i<=n; i++) {
    
    
        int tmp=i-1;
        while(a[tmp]<=a[i])
            tmp=dp[tmp];
        dp[i]=tmp;
    }
    sum[0]=0;
    for(int i=1; i<=n; i++)
        sum[i]=(sum[dp[i]]+(i-dp[i])*a[i]%mod)%mod;
    for(int i=1; i<=n; i++) {
    
    
        int si1=1;
        w[i].push_back(node(i,a[i]));
        int si=w[i-1].size();
        for(int j=0; j<si; j++) {
    
    
            ll tmp=__gcd(a[i],w[i-1][j].val);
            if(tmp==w[i][si1-1].val)
                w[i][si1-1].l=w[i-1][j].l;
            else
                w[i].push_back(node(w[i-1][j].l,tmp)),si1++;
        }
    }
    /*for(int i=1; i<=n; i++)
        for(int j=0; j<w[i].size(); j++)
            printf("%d %d %lld\n",i,w[i][j].l,w[i][j].val);*/
    for(int i=1; i<=n; i++) {
    
    
        int si=w[i].size();
        ll tmp=0;
        for(int j=0; j<si; j++) {
    
    
            int locate=ST::query(w[i][j].l,i);
            ll ans1;
            ll Sum=(sum[i]-sum[locate]+mod+a[locate]*(locate-w[i][j].l+1)%mod)%mod;
            ans1=(Sum*w[i][j].val%mod-tmp*w[i][j].val%mod+mod)%mod;
            ans=(ans+ans1)%mod;
            tmp=Sum;
            //printf("%d %d %d %lld %lld\n",i,w[i][j].l,locate,w[i][j].val,ans1);
        }
    }
    printf("%lld",ans);
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_43520313/article/details/108942792