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;
}
上一篇:Lucas学习笔记


下一篇:「CTSC2017」吉夫特【Lucas 定理】【状压DP】