【SPOJ】DIVCNT3

【题目链接】

【思路要点】

【代码】


#include<bits/stdc++.h>

using namespace std;
const int MAXN = 700005;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <typename T> void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
  write(x);
  puts("");
}
ull n, k, limit, val[MAXN], cnt[MAXN];
int m, tot, prime[MAXN], f[MAXN], home1[MAXN], home2[MAXN];
void init(int n) {
  tot = 0;
  for (int i = 2; i <= n; i++)
      f[i] = 0;
  for (int i = 2; i <= n; i++) {
      if (f[i] == 0) prime[++tot] = f[i] = i;
      for (int j = 1; j <= tot && prime[j] <= f[i]; j++) {
          int tmp = prime[j] * i;
          if (tmp > n) break;
          f[tmp] = prime[j];
      }
  }
}
ull s(ull x, int y) {
  if (x <= 1 || prime[y] > x) return 0;
  ull ans = 0;
  if (x <= limit) ans = cnt[home1[x]] - (y - 1);
  else ans = cnt[home2[n / x]] - (y - 1);
  ans *= k + 1;
  for (int i = y; i <= tot && 1ull * prime[i] * prime[i] <= x; i++) {
      ull now = prime[i], nxt = now * now;
      for (int j = 1; nxt <= x; j++, now *= prime[i], nxt *= prime[i])
          ans += s(x / now, i + 1) * (j * k + 1) + ((j + 1) * k + 1);
  }
  return ans;
}
int main() {
  int T; read(T);
  while (T--) {
      read(n), k = 3;
      limit = sqrt(n);
      init(limit);
      m = 0;
      for (ull i = 1, nxt; i <= n; i = nxt) {
          ull tmp = n / i;
          nxt = n / tmp + 1;
          val[++m] = tmp;
          cnt[m] = tmp - 1;
          if (tmp <= limit) home1[tmp] = m;
          else home2[i] = m; 
      }
      for (int i = 1; i <= tot; i++)
      for (int j = 1; 1ull * prime[i] * prime[i] <= val[j]; j++) {
          ull tmp = val[j] / prime[i];
          if (tmp <= limit) cnt[j] -= cnt[home1[tmp]] - (i - 1);
          else cnt[j] -= cnt[home2[n / tmp]] - (i - 1);
      }
      writeln(s(n, 1) + 1);
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/81568731