bzoj4176 - Lucas的数论(杜教筛,莫比乌斯反演)
题目
求
\(\sum\limits^n_{i=1}{\sum\limits^n_{J=1}{f(ij)}}\)
\(f(x)\)为x的约数个数
题解
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <unordered_map>
using namespace std;
const int N = 2000010;
typedef long long ll;
const int M = 1e9 + 7;
const int r2 = 500000004;
const int r6 = 166666668;
ll T, n;
int mu[N], prime[N], cnt;
bool vis[N];
unordered_map<ll, ll> mp_mu;
ll sum_mu[N];
ll S_mu(ll x) {
if (x < N) return sum_mu[x];
if (mp_mu[x]) return mp_mu[x];
ll ret = 1ll;
for (ll i = 2, j; i <= x; i = j + 1) {
j = x / (x / i);
ret -= S_mu(x / i) * (j - i + 1);
}
return mp_mu[x] = ret;
}
ll f(ll n) {
ll res = 0;
ll p = 1;
while(p <= n) {
ll nt = n / (n / p);
res += (n / p) * (nt - p + 1) % M;
res %= M;
p = nt + 1;
}
return res;
}
void init() {
mu[1] = 1;
for(int i = 2; i < N; i++) {
if(!vis[i]) {
prime[cnt++] = i;
mu[i] = -1;
}
for(int j = 0; j < cnt; j++) {
int p = prime[j];
if(1ll * p * i > N) break;
vis[p * i] = 1;
if(i % p == 0) {
mu[i * p] = 0;
break;
}
mu[i * p] = -mu[i];
}
}
for(int i = 1; i < N; i++) {
sum_mu[i] = sum_mu[i - 1] + mu[i];
sum_mu[i] %= M;
}
}
int main() {
init();
ll n;
cin >> n;
ll res = 0;
ll p = 1;
while(p <= n) {
ll nt = n / (n / p);
ll k = f(n / p);
res += k * k % M * (S_mu(nt) - S_mu(p - 1)) % M;
res %= M;
p = nt + 1;
}
cout << (res + M) % M << endl;
}