签到题的理解
链接 签到题
先开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;
}