标签:
2 5 1 2 3 4 5 3 1 3 2 3 1 4 4 4 2 6 9 3 1 3 2 4 2 3
9 6 16 18 23 10
预处理一段的gcd
我们发现一段的gcd是一样的
1 2 3 6 6 6 12
1 1 3 6 6 6 12 //从12开始向左的gcd
显然最多有logN段,接下来用莫队算法+杨氏转移
O(nlogn+nsqrt(n)logn)=O(n^1.5*logn)
#include<bits/stdc++.h> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define ForkD(i,k,n) for(int i=n;i>=k;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=next[p]) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define MAXN (10000+10) typedef long long ll; ll mul(ll a,ll b){return (a*b)%F;} ll add(ll a,ll b){return (a+b)%F;} ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;} void upd(ll &a,ll b){a=(a%F+b%F)%F;} int n,a[MAXN],Q; struct seg { int l,r,i; friend bool operator<(seg a,seg b){ return (int)((a.l)/sqrt(n))^(int)((b.l)/sqrt(n))?(int)((a.l)/sqrt(n))<(int)((b.l)/sqrt(n)):a.r<b.r; } }comm[MAXN]; ll ans[MAXN]; ll gcd(ll a,ll b){if (b==0) return a; return gcd(b,a%b);} int h[MAXN][100]={0}; ll val[MAXN][100]={0}; void init(int h[][100],ll val[][100]) { MEM(val) MEM(h) For(i,n) h[i][0]=0; h[1][0]=1; h[1][1]=1; val[1][1]=a[1]; Fork(i,2,n) { int &k=h[i][0]; val[i][++k]=a[i];h[i][k]=i; For(j,h[i-1][0]) { ll p=gcd(val[i][k],val[i-1][j]); if (p!=val[i][k]) val[i][++k]=p; h[i][k]=h[i-1][j]; } } } int h2[MAXN][100]={0}; ll val2[MAXN][100]={0}; void init2(int h[][100],ll val[][100]) { MEM(val) MEM(h) For(i,n) h[i][0]=0; h[n][0]=1; h[n][1]=n; val[n][1]=a[n]; ForD(i,n-1) { int &k=h[i][0]; val[i][++k]=a[i];h[i][k]=i; For(j,h[i+1][0]) { ll p=gcd(val[i][k],val[i+1][j]); if (p!=val[i][k]) val[i][++k]=p; h[i][k]=h[i+1][j]; } } } ll modify(){return 0; } ll modify(int l,int r,int f) { ll ret=0; if (f==0) { //left int fro=l; For(j,h2[l][0]) { int last=min(h2[l][j],r); if (fro<=last) ret+=val2[l][j]*(last-fro+1); fro=last+1; if (fro>r) break; } } else { int last=r; For(j,h[r][0]) { int fro=max(h[r][j],l); if (fro<=last) ret+=val[r][j]*(last-fro+1); last=fro-1; if (fro<l) break; } } return ret; } int main() { // freopen("B.in","r",stdin); int T; cin>>T; while(T--) { cin>>n; For(i,n) scanf("%d",&a[i]); init(h,val);init2(h2,val2); cin>>Q; MEM(ans) For(i,Q) { scanf("%d%d",&comm[i].l,&comm[i].r),comm[i].i=i; } sort(comm+1,comm+1+Q); int nowl=1,nowr=1; ll nowans=a[1]; For(i,Q) { while (nowl<comm[i].l) nowans-=modify(nowl,nowr,0),nowl++; while (nowl>comm[i].l) nowans+=modify(nowl-1,nowr,0),nowl--; while (comm[i].r<nowr) nowans-=modify(nowl,nowr,1),nowr--; while (comm[i].r>nowr) nowans+=modify(nowl,nowr+1,1),nowr++; ans[comm[i].i]=nowans; } For(i,Q) printf("%I64d\n",ans[i]); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5381(The sum of gcd-莫队算法解决区间段gcd的和)
标签:
原文地址:http://blog.csdn.net/nike0good/article/details/48057429