Wannafly挑战赛7 E:珂朵莉与GCD

题目传送门

树状数组可解

代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=100000+100;
const ll mod=1e9+7;

struct Node{

    int l,r;
    int id;
}node[maxn];
ll ans[maxn];
ll gc[maxn];
ll Ans[maxn];
int pos[maxn];
ll bit[maxn][2];
int n,m;

inline int lowbit(int x){

    return x&(-x);
}

inline void Add(int x,ll v){

    int tmp=x;
    while(x<=n){

        bit[x][0]+=v;
        bit[x][1]+=tmp*v;
        x+=lowbit(x);
    }
}

inline ll getSum(int x){

    ll sum=0;
    int tmp=x;
    while(x>0){

        sum+=(ll)(tmp+1)*bit[x][0]-bit[x][1]; 
        sum%=mod;
        x-=lowbit(x);
    }
    return sum;
}

inline ll gcd(ll a,ll b){

    return b==0?a:gcd(b,a%b);
}

inline bool cmp(Node a,Node b){

    return a.r<b.r;
}

int main(){

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&ans[i]);
    for(int i=1;i<=m;i++) scanf("%d%d",&node[i].l,&node[i].r),node[i].id=i;
    sort(node+1,node+1+m,cmp);
    int p=1;
    int tot=0;
    for(int i=1;i<=m;i++){

        while(p<=node[i].r){

            for(int j=1;j<=tot;j++) gc[j]=gcd(gc[j],ans[p]);
            gc[++tot]=ans[p];
            pos[tot]=p;
            int tmp=0;
            for(int j=1;j<=tot;j++) if(gc[j]!=gc[j-1]) {

                gc[++tmp]=gc[j];
                pos[tmp]=pos[j];
            }
            tot=tmp;
            for(int j=1;j<tot;j++){

                Add(pos[j],gc[j]);
                Add(pos[j+1],-gc[j]); 
            }
            Add(pos[tot],gc[tot]);
            Add(p+1,-gc[tot]);
            p++;
        }
        Ans[node[i].id]=getSum(node[i].r)-getSum(node[i].l-1);
    }
    for(int i=1;i<=m;i++) printf("%lld\n",Ans[i]%mod);
}

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/81349934