[洛谷P5190][COCI 2010] PROGRAM

本文详细解析了一种数论求和算法,该算法能在O(nlogn)的时间复杂度内,通过预处理每个数的出现次数并将其加到其倍数上,实现对k个数的约数在l到r范围内的求和。文章提供了C++代码实现,并讨论了算法的细节及注意事项。

题目大意:给你$k(k\leqslant10^6)$个数,$f(x)$表示$x$的约数在$k$个数中出现的次数,在这任何数都是$0$的约数。$m(m\leqslant10^6)$次询问,每次给出$l,r(l,r\leqslant10^6)$,求$\sum\limits_{i=l}^rf(i)$

题解:求出每个数出现次数,直接加到它的倍数上,$O(n\log_2n)$,然后前缀和,直接输出,注意$l=0$的情况

卡点:

 

C++ Code:

#include <cstdio>
#define maxn 1000010
int n, k, m;
long long __pre__[maxn], *pre = __pre__ + 1;
int cnt[maxn];
int main() {
	scanf("%d%d", &n, &k);
	for (int i = 0, x; i < k; ++i) {
		scanf("%d", &x);
		++cnt[x];
	}
	for (int i = 1; i < n; ++i) {
		for (int j = 0; j < n; j += i) pre[j] += cnt[i];
	}
	for (int i = 1; i < n; ++i) pre[i] += pre[i - 1];
	scanf("%d", &m);
	while (m --> 0) {
		static int l, r;
		scanf("%d%d", &l, &r);
		printf("%lld\n", pre[r] - pre[l - 1]);
	}
	return 0;
}

  

转载于:https://www.cnblogs.com/Memory-of-winter/p/10356622.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值