HDU 5381 (The sum of gcd-teams algorithm solves The sum of gcd segments), hdugcd-
The sum of gcd
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission (s): 784 Accepted Submission (s): 335
Problem DescriptionYou have an array A , The length A Is N
Let F (l, r) = Σ ri = l Σ rj = igcd (ai, ai + 1... aj)
InputThere are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
First line has one integers N
Second line has N Integers Ai
Third line has one integers Q , The number of questions
Next there are Q lines, each line has two integers L , R
1 ≤ T ≤ 3
1 ≤ n, Q ≤ 104
1 ≤ ai ≤ 109
1 ≤ l <r ≤ n
OutputFor each question, you need to print F (l, r)
Sample Input
251 2 3 4 531 32 31 444 2 6 931 32 42 3
Sample Output
9616182310
AuthorSXYZ
Source2015 Multi-University Training Contest 8
Recommendwange2014 | We have carefully selected several similar problems for you: 5421 5420 5419 5418
Preprocessing a piece of gcd
We found that a piece of gcd is the same.
1 2 3 6 6 12
1 1 3 6 6 6 12 // start from 12 to the left gcd
Apparently, there are a maximum of logN segments. Next we will use the mo team Algorithm + Young's transfer
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;}
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.