质数筛+埃氏筛取思想

签到题的理解

链接 签到题
质数筛+埃氏筛取思想_第1张图片

质数筛+埃氏筛取思想_第2张图片
先开e6+5数组线性筛出<=e6的质数,再计算出每个质数对于l,r之间的值的贡献度,先得出不互质的个数,在减去即可。具体筛取从2到sqrt(r)。
A[i]是不互质个数,B[i]是检测在筛选范围中能否筛选全,一开始赋值都为l到r区间的值。筛选时B[i]/=例举质数,而A[i]=A[i]/例举质数(例举质数-1)。*
筛取结束若B[i]!=1说明有因子>=sqrt(r),则特判。(数组前移l单位)
例如 输入 20 30
处理过程
i A[i] B[i]

0 10 5
2 11 11
4 12 3
6 13 13
8 14 7
10 15 15
1 14 7
4 8 1
7 18 1
10 10 5
0 8 1
5 20 1
10 8 1

处理结果
i A[i] B[i]
0 8 1
1 14 7
2 11 11
3 23 23
4 8 1
5 20 1
6 13 13
7 18 1
8 14 7
9 29 29
10 8 1

include<iostream>
#define ll long long
using namespace std;
const int mod = 1e6 + 5;
bool nu[mod];ll a[mod];
ll A[mod], B[mod];ll l, r, ba;
long long ans = 0;
void p()
{
	int cnt = 0;
	for (int i = 2;i < mod;i++)
	{
		if (!nu[i]) a[cnt++] = i;
		for (int j = 0;j < cnt&&i*a[j]<mod;j++)
		{
			nu[i * a[j]] = true;
			if (i % a[j] == 0) break;
		}
	}
}
void k()
{
	int i = 0;
	while (a[i] * a[i] <= r)
	{
		ll p = a[i];
		for (int j = (p - l % p) % p;j <= r - l;j += p)
		{
			A[j] /= p;A[j] *= (p - 1);
			while (B[j] % p == 0) B[j] /= p;
		}i++;
	}
}
int main()
{
	p();cin >> l >> r;ba = l;
	for (ll i = l;i <= r;i++) A[i - ba] = B[i - ba] = i;
	k();
	for (int i = 0;i <= r - l;i++)
	{
		if (B[i] != 1) A[i] /= B[i], A[i] *= (B[i] - 1);
		ans = (ans + i + l - A[i]) % 666623333;
	}
	cout << ans;
}

你可能感兴趣的:(算法)