UOJ188. 【UR13】Sanrd

看到因子,还是多想想Min_25筛吧。

解释下

  • 如果$p_k$是次大因子,那么只要选出$[p_k,n/p_j^e]$中的质数.
  • 如果$p_k$不是是次大因子,那么次大因子就是$\sum_{i=1}^{n/p_k^e}[min(i)>p_k] f(i)$.
  • 注意边界$p_j> n^2$,还是恒没有贡献。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
#define mk make_pair
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
struct Min_25
{
ll n, Lim;
ll g[N], p[N];
int pos1[N], pos2[N], cnt;
int pcnt;
ll pr[N], npr[N];
void Prime_init(int X)
{
for (int i = 2; i <= X; i++)
{
if (!npr[i])
{
pr[++pcnt] = i;
}
for (int j = 1; j <= pcnt && pr[j] * i <= X; j++)
{
npr[i * pr[j]] = 1;
if (i % pr[j] == 0)
break;
}
}
}
int Getcnt(ll x)
{
return (x <= Lim) ? pos1[x] : pos2[n / x];
}
ll S(ll x, int y)
{
if (pr[y] >= x || x <= 2)
return 0;
ll ans = 0;
for (int i = y + 1; i <= pcnt && pr[i] * pr[i] <= x; i++)
{
ll pe = pr[i];
for (int e = 1; pe * pr[i] <= x; e++, pe = pe * pr[i])
{
int k = Getcnt(x / pe);
ans += (S(x / pe, i));

//cout << pr[i] << " " << e << ' ' << g[k] - (i - 1) << endl;
ans += pr[i] * (g[k] - (i - 1));
}
}
return ans;
}

ll get(ll x)
{
n = x;
Lim = sqrt(n);
Prime_init(Lim);

for (ll i = 1, j; i <= n; i = j + 1)
{
j = n / (n / i);
ll k = n / i;
p[++cnt] = k;
g[cnt] = k - 1;
if (k <= Lim)
pos1[k] = cnt;
else
pos2[n / k] = cnt;
}

for (int i = 1; i <= pcnt; i++)
{
for (int j = 1; j <= cnt && 1ll * pr[i] * pr[i] <= p[j]; j++)
{
int k = Getcnt(p[j] / pr[i]);
g[j] -= g[k] - (i - 1);
}
}

return S(n, 0);
}
} T1, T2;
ll l, r;
int main()
{
// cin >> r;
// cout << T1.get(r) << endl;
cin >> l >> r;
cout << T2.get(r) - T1.get(l - 1) << endl;
}