The sum of GCDTime
limit:2000/1000 MS (java/others) Memory limit:65536/65536 K (java/others)
Total submission (s): Accepted submission (s): 4
Problem Descriptionyou has an arrayThe length ofIs
Let
Inputthere is multiple test cases. The first line of input contains an integer T, indicating the number of the test cases. For each test case:
First line have one integers
Second Line hasIntegers
Third line have one integersThe number of questions
Next there is Q Lines,each line has both integers,
Outputfor each question,you need to print
Sample Input
251 2 3 4 531 32 31 444 2 6 931 32 42 3
Sample Output
9616182310
Source2015 multi-university Training Contest 8
The sum of the gcd of the arbitrary sub-range within an interval.
Analysis:
The complexity of the sum of the gcd of the interval [l,r] is Nlog (n)
::
If the results of [l,r] are processed, then for [l,r+1]. The new sub-range that can be produced is [r-l+1]. How to merge?
Because of the increase of r+1, then [L,r+1], (L<=L<=R) must be through the R position. Know the GCD of R with each previous position.
With Num[r+1] and these gcd values, do GCD to get a new GCD value, which is the GCD result of all new sub-ranges. For each gcd multiplied by the corresponding
The number of intervals is possible.
Of course, the more left. The smaller the GCD, the more log gcd values appear. Merging the same GCD can reduce the amount of computation.
Then the newly added number itself can become an interval, adding to the answer.
The complexity of the processing is nlog, because of the chunking,
Up to sqrt (n) of length n, complexity is Nlog (n) *sqrt (n)
Within the block. The length is sqrt (n) and is calculated most times. All Qlog (n) *sqrt (n) ================== (log (n) is the number of species GCD)
Now we are working on merging two paragraphs:
Because it is divided into two segments, such as the following
Original sequence: 1 1 1 2 2 2 4 4 4| 4 4 4 2 2 2 1 1 1 (| is a separate position)
Gcd:1 1 1 2 2 2 4 4 4 | 4 4 4 2 2 2 1 1 1
GCD calculates the gcd of this point to the path of the cutting position, since the merger must be cut in place!
It is clear that the GCD species has only log (n). For each of the GCD on the left and the GCD on the right, do a gcd function. and multiply it by the left part.
Length * The length of the paragraph to the right. As the example is
GCD (*3*3+GCD) *3*3 + gcd (1,4) *3*3) ...........
How to calculate the corresponding interval number of each GCD?
It is possible to know that the GCD from the dividing line to both sides is decremented. Assuming that G is the gcd of [L,r], then for [L-1,r] only gcd (g,num[l-1]) is calculated.
Then the GCD hypothesis is the same as that of G. Otherwise, a new value is added.
Analysis of Complexity:
For each paragraph, the total GCD and the number of O (n) are calculated.
The long section is sqrt (n). is N*sqrt (n). Short is sqrt (n) *q times
Merge time complexity is Q*log (n) *log (n), so O (sqrt (n) *n+q*sqrt (n) +q*log (n) *log (n))
Next look at the code:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include < vector>using namespace std; #define MAXN 20001#define ll long longint gcd (int a,int b) {if (b = = 0) return A; return gcd (b,a%b);} ll ans[maxn];struct node{int l,r,id;}; Node Que[maxn];int length;//chunked sorting function int comp (Node A,node b) {if (a.l/length = = b.l/length) return A.R < B.R; return A.l/length < B.l/length;} int num[maxn];struct point{int g,num; Point (int _g=0,int _n=0): g (_g), num (_n) {}};vector<point> lgcd;vector<point> ltrgcd;vector<point> rgcd;vector<point> Rtlgcd;int Main () {int t,n,q; scanf ("%d", &t); while (t--) {scanf ("%d", &n); for (int i = 0;i < n; i++) scanf ("%d", num+i); scanf ("%d", &q); for (int i = 0;i < Q; i++) {scanf ("%d%d", &QUE[I].L,&QUE[I].R); Que[i].id = i; QUE[I].L--, que[i].r--; } for (length = 1; Length * length < n; length++); Sort (que,que+q,comp);//Sort by fast, the same block r from small to large memset (ans,0,sizeof (ans)); Lgcd.clear (); Rgcd.clear (); Ltrgcd.clear (); Rtlgcd.clear (); int RR = -1,kuai = -1,j,k,l,ll; ll res = 0,RESL = 0; Point A; for (int i = 0;i < Q; i++) {handles Each of the Ask if (Kuai! = que[i].l/length) {//new block. So a long paragraph to start with the processing Kuai = Que[i].l/length; Rtlgcd.clear (); Rgcd.clear (); RR = kuai*length+length-1; res = 0; } while (RR < QUE[I].R) {rr++;//handles the sum of GCD of the separator line to RR.
for (j = 0;j < Rgcd.size (); j + +) {rgcd[j].g = gcd (Rgcd[j].g,num[rr]); Res + = (ll) rgcd[j].g*rgcd[j].num; } rgcd.push_back (Point (num[rr],1)); Res + = NUM[RR]; for (j = 0,k = 1;k<rgcd.size (); k++) {if (rgcd[j].g = = rgcd[k].g) {rgcd[j].num + = Rgcd[k].num; } else {j + +; RGCD[J] = rgcd[k]; }} while (Rgcd.size () > J+1) rgcd.pop_back ();//merge the same GCD//processing divider to each RR's GCD Number if (rtlgcd.size () = = 0) rtlgcd.push_back (Point (num[rr],1)); else {k = rtlgcd.size () -1;//just need to be the smallest one gcd. GCD A.G = gcd (RTLGCD[K].G,NUM[RR]), which is the rightmost calculation; A.num = 1; if (A.G = = RTLGCD[K].G) rtlgcd[k].num++; else Rtlgcd.push_back (a); }} LL = Kuai*length+length-1; Lgcd.clear (); Ltrgcd.clear (); Resl = 0;//The left side of the handle is the same as the right one LL = min (LL,QUE[I].R); for (; LL >= QUE[I].L; ll--) {for (j = 0;j < Lgcd.size (); j + +) {lgcd[j].g = gcd (Lgcd[j].g,num[ll]); Resl + = (ll) lgcd[j].g*lgcd[j].num; } lgcd.push_back (Point (num[ll],1)); Resl + = Num[ll]; for (j = 0,k=1;k<lgcd.size (); k++) {if (lgcd[j].g = = lgcd[k].g) {Lgcd[j].num + = Lgcd[k].num; } else {j + +; LGCD[J] = lgcd[k]; }} while (Lgcd.size () > J+1) lgcd.pop_back (); if (ltrgcd.size () = = 0) {ltrgcd.push_back (num[ll],1)); } else {k = Ltrgcd.size ()-1; A.G = gcd (Ltrgcd[k].g,num[ll]); A.num = 1; if (A.G = = ltrgcd[k].g) ltrgcd[k].num++; else Ltrgcd.push_back (a); }}//merge two intervals ans[que[i].id] = res + resl; int id = QUE[I].ID,GG; for (j = 0;j < Ltrgcd.size (); j + +) {GG = LTRGCD[J].G; for (k = 0;k < Rtlgcd.size (); k++) {GG = gcd (GG,RTLGCD[K].G); Ans[id] + = (ll) gg*ltrgcd[j].num*rtlgcd[k].num; }}} for (int i = 0;i < Q; i++) {printf ("%i64d\n", Ans[i]); }} return 0;}
HDU 5381 The sum of GCD 2015 multi-school joint training game # MO team algorithm