隐藏
「51nod1244」莫比乌斯函数之和 - 杜教筛 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「51nod1244」莫比乌斯函数之和 - 杜教筛

题目大意

    求$\sum_{i=x}^y\mu(i)$。


题目分析

又一道杜教筛入门题。
为了下文描述方便,我们记$M(n)=\sum_{i=1}^n\mu(i)$。

根据众所周知的结论:

我们有:

预处理$n^\frac23$以内的$M(i)$,使用杜教筛递归计算。


代码

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
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<climits>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;

typedef long long LL;
#define pii pair<LL,LL>
#define mp make_pair

inline const LL Get_Int() {
LL num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}

const int limit=5000000;
const LL hashmod=999959;

bool vst[limit+5];
int cnt=0,Prime[limit+5],Mobius[limit+5];
vector<pii>Hash[hashmod+5];

void Table(int n) {
Mobius[1]=1;
for(int i=2; i<=n; i++) {
if(!vst[i]) {
Prime[++cnt]=i;
Mobius[i]=-1;
}
for(int j=1; j<=cnt&&i*Prime[j]<=n; j++) {
vst[i*Prime[j]]=1;
if(i%Prime[j]==0) {
Mobius[i*Prime[j]]=0;
break;
}
Mobius[i*Prime[j]]=-Mobius[i];
}
}
for(int i=2; i<=n; i++)Mobius[i]+=Mobius[i-1];
}

void Add(int x,LL p,LL v) {
Hash[x].push_back(mp(p,v));
}

LL Cal(LL n) {
if(n<=limit)return Mobius[n];
for(pii x:Hash[n%hashmod])if(x.first==n)return x.second;
LL Next,ans=0;
for(LL i=2; i<=n; i=Next+1) {
Next=n/(n/i);
ans+=(Next-i+1)*Cal(n/i);
}
ans=1-ans;
Add(n%hashmod,n,ans);
return ans;
}

int main() {
Table(limit);
LL x=Get_Int(),y=Get_Int();
printf("%lld\n",Cal(y)-Cal(x-1));
return 0;
}
姥爷们赏瓶冰阔落吧~