您的位置:首页 > 其它

hdu 5381 The sum of gcd(线段树)

2016-05-28 14:33 459 查看


The sum of gcd

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 1056    Accepted Submission(s): 465


Problem Description

You have an array A,the
length of A is n

Let f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj)

 

Input

There 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

 

Output

For each question,you need to print f(l,r)

 

Sample Input

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

 

Sample Output

9
6
16
18
23
10

 

Author

SXYZ
#include<cstdio>
#include<algorithm>
using namespace std;
#define ls t<<1
#define rs (t<<1)|1
const int maxn = 1e4 + 200;
int val[maxn],n, m;
struct node
{
int lg[32], rg[32], ln[32], rn[32], cntl, cntr;
long long sum;
}tree[maxn<<2],ans;
int gcd(int a, int b)
{
if (b == 0)return a;
return gcd(b, a%b);
}
node Union(node a, node b)
{
node ret;
ret.sum = a.sum + b.sum;
for (int i = 0; i < a.cntr; i++)
for (int j = 0; j < b.cntl; j++)
ret.sum += 1ll * gcd(a.rg[i], b.lg[j])*a.rn[i] * b.ln[j];
for (int i = 0; i < a.cntl; i++)
{
ret.lg[i] = a.lg[i];
ret.ln[i] = a.ln[i];
}
for (int i = 0; i < b.cntr; i++)
{
ret.rg[i] = b.rg[i];
ret.rn[i] = b.rn[i];
}
int d = b.rg[b.cntr - 1], pos = b.cntr;
for (int i = 0; i < a.cntr; i++)
{
int tmp = gcd(d, a.rg[i]);
if (tmp == ret.rg[pos - 1])ret.rn[pos - 1] += a.rn[i];
else
{
ret.rg[pos] = tmp;
ret.rn[pos++] = a.rn[i];
}
}
ret.cntr = pos;
d = a.lg[a.cntl - 1], pos = a.cntl;
for (int i = 0; i < b.cntl; i++)
{
int tmp = gcd(d, b.lg[i]);
if (tmp == ret.lg[pos - 1])ret.ln[pos - 1] += b.ln[i];
else {
ret.lg[pos] = tmp;
ret.ln[pos++] = b.ln[i];
}
}
ret.cntl = pos;
return ret;
}
void build(int l, int r, int t)
{
if (l == r)
{
tree[t].cntl = tree[t].cntr = 1;
tree[t].sum = tree[t].rg[0] = tree[t].lg[0] = val[l];
tree[t].ln[0] = tree[t].rn[0] = 1;
return;
}
build(l, (l + r) / 2, ls);
build((l + r) / 2 + 1, r, rs);
tree[t] = Union(tree[ls], tree[rs]);
}
void query(int l, int r,int lt,int rt, int t)
{
if (lt<=l&&rt>=r)
{
if (lt==l)ans = tree[t];
else ans=Union(ans, tree[t]);
return;
}
int mid = (l+r) / 2;
if (lt <= mid)query(l,mid,lt,rt, ls);
if (rt > mid)query(mid+1,r,lt,rt, rs);
}
int main()
{
int t,l,r;
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &val[i]);
build(1, n, 1);
scanf("%d", &m);
while (m--)
{
scanf("%d%d", &l, &r);
query(1,n,l,r,1);
printf("%I64d\n", ans.sum);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: