HDU 5381 The sum of gcd

对于每个i,求出若干区间[l1,r1],[l2,r2],[l3,r3]...满足gcd(l1~i)~gcd(r1~i)一样,gcd(l2~i)~gcd(r2,i)一样...

则以i为右区间的所有gcd和为sum[i] = (r1 - l1 + 1) * g1 + (r2 - l2 + 1) * g2 + ...

同理求出i右边的一段段同gcd区间[l11,r11],[l22,r22],[l33,r33]...

然后将询问按左区间排序,int p初始设为1,对于p <= i < L,要消除i对所有前缀和的影响,只要[l11,r11]的sum[]减去g11,[l22,r22]的sum[]减去g22...

p = L

ans = [L,R]的sum和

求i的区间时,先保留i-1求出的区间,然后A[i]和每个区间的g求gcd,该合并的合并

(队友A的,就不贴他优雅的代码了, 红红火火恍恍惚惚)


struct Node {
	int l, r, g;

	Node() {}
	Node(int l, int r, int g): 
	l(l), r(r), g(g) {
	}
}nodes[N];


int m = 0;
for(int i = 1; i <= n; i ++) {
	rep(j, m) {
		nodes[j].g = std::__gcd(nodes[j].g, a[i]);
	}
	nodes[m ++] = Node(i, i, a[i]);
	int t = 0;
	for(int j = 1; j < m; j ++) {
		if(nodes[j].g == nodes[t].g) {
			nodes[t].r = nodes[j].r;
		} else {
			nodes[++ t] = nodes[j];
		}
	}
	t++;
	m = t;
	LL sum = 0;
	rep(j, m) {
		sum += (nodes[j].r - nodes[j].l + 1LL) * nodes[j].g;
	}
	Stree.L = i;
	Stree.R = i;
	Stree.val = sum;
	Stree.update(1, n, 1);
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值