QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#650596 | #8327. 积性函数求和 $10^{13}$ 方便 FFT 版 | zydy | WA | 0ms | 3712kb | C++17 | 11.6kb | 2024-10-18 15:45:51 | 2024-10-18 15:45:52 |
Judging History
answer
#include <iostream>
#include <vector>
#include <cmath>
#include <functional>
#include <algorithm>
#include <time.h>
#include <fstream>
using namespace std;
using u32 = unsigned int;
using u64 = unsigned long long;
using i64 = long long;
constexpr u32 mod = 469762049;
inline constexpr u32 norm(const u32 x) { return x < mod ? x : x - mod; }
struct m32 {
u32 x;
m32() { }
constexpr m32(const u32 _x) : x(_x) { }
};
inline constexpr m32 operator + (const m32 x1, const m32 x2) { return norm(x1.x + x2.x); }
inline constexpr m32 operator - (const m32 x1, const m32 x2) { return norm(x1.x + mod - x2.x); }
inline constexpr m32 operator - (const m32 x) { return x.x ? mod - x.x : 0; }
inline constexpr m32 operator * (const m32 x1, const m32 x2) { return static_cast<u64>(x1.x) * x2.x % mod; }
inline m32& operator += (m32& x1, const m32 x2) { return x1 = x1 + x2; }
inline m32& operator -= (m32& x1, const m32 x2) { return x1 = x1 - x2; }
inline m32& operator *= (m32& x1, const m32 x2) { return x1 = x1 * x2; }
inline bool operator == (const m32 x1, const m32 x2) { return x1.x == x2.x; }
inline bool operator != (const m32 x1, const m32 x2) { return x1.x != x2.x; }
struct block {
static int v;
vector<m32> sv;
vector<m32> lv;
block() : sv(v + 1, 0), lv(v + 1, 0) {}
};
int block::v;
inline void add(m32& x, const u32 a, const u32 b) { x = (x.x + 1ULL * a * b) % mod; }
inline void add(m32& x, const m32 a, const m32 b) { add(x, a.x, b.x); }
inline void sub(m32& x, const m32 a, const m32 b) { add(x, a.x, mod - b.x); }
block solve(const i64 N, m32 A, m32 B) {
const int v = sqrt(N + 0.5);
const int n_4 = sqrt(v + 0.5);
const int n_8 = sqrt(n_4 + 0.5);
block::v = v;
vector<int> primes;
vector<int> pi(v + 1);
vector<bool> is_prime(v + 1);
primes.push_back(1);
is_prime[2] = true;
for (int i = 3; i <= v; i += 2) is_prime[i] = true;
for (int i = 3; i * i <= v; i += 2)
for (int j = i * i; is_prime[i] && j <= v; j += (i << 1))
is_prime[j] = false;
for (int i = 2; i <= v; ++i) {
pi[i] = pi[i - 1] + is_prime[i];
if (is_prime[i]) primes.push_back(i);
}
vector<m32> sup;
sup.resize(primes.size());
u32 rec[4];
rec[1] = 1;
for (int i = 2; i <= 3; ++i)
rec[i] = (i64)(mod - mod / i) * rec[mod % i] % mod;
m32 inv3 = m32(rec[3]);
const auto divide = [](i64 n, i64 d) -> i64 {return double(n) / d; };
const auto divide_32 = [](i64 n, int d) -> int {return double(n) / d; };
auto calc_medium = [&](const function<m32(u64)>& fp) {
sup.clear();
sup[0] = m32(0);
for (int i = 1; i <= pi[v]; ++i) sup[i] = fp(primes[i]);
vector<m32> lq(v + 1, 0);
for (int i = 1; i <= pi[v]; ++i) lq[primes[i]] += sup[i];
for (int i = 1; i <= v; ++i) lq[i] += lq[i - 1];
block f;
const i64 K1 = max<i64>(min((i64)pow(N, 2.0 / 3) * 4, N), v + 1);
const int _v = sqrt(K1), B1 = N / K1;
for (int i = pi[n_4] + 1; i <= pi[_v]; ++i) {
const i64 M = N / primes[i];
const int t = pi[min(divide_32(K1, primes[i]), v)];
for (int j = i; j <= t; ++j) f.lv[divide_32(M, primes[j])] += sup[i] * sup[j];
}
for (int i = v - 1; i > B1; --i) f.lv[i] += f.lv[i + 1];
for (int k = 1; k <= B1; ++k) {
f.lv[k] = m32(0);
const i64 M = N / k;
const int t1 = pi[sqrt(M + 0.5)], t0 = pi[v / k];
int j = pi[n_4] + 1;
for (; j <= t0; ++j) f.lv[k] += sup[j] * (lq[v] - lq[primes[j - 1]]);
for (; j <= t1; ++j) f.lv[k] += sup[j] * (lq[divide_32(M, primes[j])] - lq[primes[j - 1]]);
}
for (int k = 1; k <= n_4; ++k) {
int t = v / k;
i64 m = N / k;
m32 ans = m32(0);
for (int i = pi[n_4] + 1; i <= pi[t]; ++i) ans += sup[i] * f.lv[primes[i] * k];
for (int i = pi[n_4] + 1; i <= pi[t]; ++i) {
i64 q = (i64)primes[i] * primes[i];
if (q * n_4 > m) break;
ans += sup[i] * sup[i] * (lq[divide(m, q)] - lq[n_4]);
}
t = cbrt(m + 0.5);
for (int i = pi[n_4] + 1; i <= pi[t]; ++i) ans += sup[i] * sup[i] * sup[i];
f.lv[k] += ans * inv3;
}
for (int i = 1; i <= v; ++i) f.lv[i] += lq[v] - lq[n_4] + 1;
for (int i = 1; i <= n_4; ++i) f.sv[i] = 1;
for (int i = n_4 + 1; i <= v; ++i) f.sv[i] = lq[i] - lq[n_4] + 1;
for (int i = 0; i <= v; ++i) lq[i] = 0;
vector<m32> sq(v + 1, 0);
int mm = v * max(log(N) / 10, 1.);
int K = min(N, (i64)(mm * pow(N, 0.125))), B = N / K;
m32 sum_s = 0;
const auto add_s = [&](int x, m32 cnt) -> void {
sum_s += cnt;
while (x <= v) sq[x] += cnt, x += x & -x;
};
const auto add_l = [&](int x, m32 cnt) -> void {
x = v + 1 - x;
while (x <= v) lq[x] += cnt, x += x & -x;
};
function <void(int, int, m32)> dfs = [&](int n, int id, m32 fn) {
if (n <= v) add_s(n, fn);
else add_l(divide_32(N, n), fn);
for (int i = id; i <= pi[v]; ++i) {
i64 q = (i64)n * primes[i];
if (q > K) break;
dfs(q, i, fn * sup[i]);
}
};
auto query_s = [&](int x) -> m32 {
m32 ans = f.sv[x];
while (x) ans += sq[x], x ^= x & -x;
return ans;
};
auto query_l = [&](int x) -> m32 {
x = v + 1 - x;
m32 ans = sum_s;
while (x) ans += lq[x], x ^= x & -x;
return ans;
};
int K2, B2;
for (int id = pi[n_4]; id > pi[n_8]; --id) {
const int p = primes[id];
const u64 m = N / p;
dfs(p, id, sup[id]);
const int t0 = B / p, t1 = min(B, v / p);
for (int i = B; i > t1; --i) add(f.lv[i], sup[id], query_s(divide_32(m, i)));
for (int i = t1; i > t0; --i) add(f.lv[i], sup[id], f.lv[i * p] + query_l(i * p));
for (int i = t0; i; --i) add(f.lv[i], sup[id], f.lv[i * p]);
K2 = mm * sqrt(p);
B2 = N / K2;
for (int i = B2; i > B; --i) f.lv[i] += query_l(i);
K = K2, B = B2;
}
for (int i = B + 1; i <= v; ++i) f.lv[i] += query_l(i);
for (int i = 1; i <= v; ++i)
if (i & (i - 1))
sq[i] += sq[i & (i - 1)];
for (int i = 1; i <= v; ++i) f.sv[i] += sq[i];
return f;
};
auto attach_small = [&](block&& f, const function<m32(u64)>& fp) {
for (int id = pi[n_8]; id; --id) {
const int p = primes[id], t = v / p;
const i64 m = N / p;
for (int j = 1, i = p; j <= t; ++j) {
const m32 c1 = sup[id] * f.sv[j];
for (int e = min(v + 1, i + p); i < e; ++i) f.sv[i] += c1;
}
for (int i = v; i > t; --i) add(f.lv[i], sup[id], f.sv[divide_32(m, i)]);
for (int i = t; i >= 1; --i) add(f.lv[i], sup[id], f.lv[i * p]);
}
return move(f);
};
auto calc_large = [&](const function<m32(u64)>& fp, const function<m32(u64)>& sum_fp) {
block f = attach_small(calc_medium(fp), fp);
block res;
for (int i = v; i >= 1; --i) {
m32 ans = sum_fp(N / i) - f.lv[i];
for (int j = 2; i * j <= v; ++j) sub(ans, fp(j), res.lv[i * j]);
res.lv[i] = ans;
}
return res;
};
auto mult_large = [&](block&& f, const block& l) {
for (int i = 1; i <= v; ++i) {
for (int j = 1; i * j <= v; ++j)
if (f.sv[j] != f.sv[j - 1])
add(f.lv[i], f.sv[j] - f.sv[j - 1], l.lv[i * j]);
}
return move(f);
};
auto mult_powerful = [&](block&& f, const function<m32(u32, u32)>& fpp) {
m32 s_sum = f.sv[v];
for (int i = v; i >= 1; --i) {
if (i & (i - 1)) f.lv[v + 1 - i] -= f.lv[v + 1 - (i & (i - 1))];
else f.lv[v + 1 - i] -= s_sum;
}
for (int i = v; i >= 1; --i)
if (i & (i - 1)) f.sv[i] -= f.sv[i & (i - 1)];
const auto sum_s = [&](int i, int j) -> m32 {
const int m = i & (~u64(0) << (64 - __builtin_clzll(i ^ j)));
m32 ret = m32(0);
while (i > m) ret -= f.sv[i], i &= i - 1;
while (j > m) ret += f.sv[j], j &= j - 1;
return ret;
};
const auto sum_l = [&](int i, int j) -> m32 {
i = v + 1 - i;
j = v + 1 - j;
const int m = i & (~u64(0) << (64 - __builtin_clzll(i ^ j)));
m32 ret = m32(0);
while (i > m) ret -= f.lv[v + 1 - i], i &= i - 1;
while (j > m) ret += f.lv[v + 1 - j], j &= j - 1;
return ret;
};
const auto common = [&](int i, int j) -> int {
const int mask = (~u64(0) >> 1) >> __builtin_clzll(i ^ j);
const int m = (i & mask) == 0 ? (i + (i & -i)) : (j & mask) != 0 ? ((j & ~mask) + mask + 1) : j;
return (m > v) ? v : m;
};
const auto add_s_fix = [&](int i, int m) -> void {
for (int k = i + (i & -i); k <= m; i = k, k += k & -k) f.sv[k] += f.sv[i];
};
const auto add_s = [&](int i, int j, m32 s) -> void {
const int m = common(i, j);
add_s_fix(j, m);
m32 t = f.sv[i];
f.sv[i] = t + s;
for (i += i & -i; i <= m; i += i & -i) f.sv[i] -= t, t += f.sv[i];
};
const auto add_l_fix = [&](int i, int m) -> void {
for (int k = i + (i & -i); k <= m; i = k, k += k & -k) f.lv[v + 1 - k] += f.lv[v + 1 - i];
};
const auto add_l = [&](int i, int j, m32 s) -> void {
i = v + 1 - i;
j = v + 1 - j;
const int m = common(i, j);
add_l_fix(j, m);
m32 t = f.lv[v + 1 - i];
f.lv[v + 1 - i] = t + s;
for (i += i & -i; i <= m; i += i & -i)
f.lv[v + 1 - i] -= t, t += f.lv[v + 1 - i];
};
const auto add_l2 = [&](int i, m32 s) -> void {
int t = v + 1 - i, nt = t + (t & -t);
if (nt <= v) f.lv[v + 1 - nt] -= f.lv[i];
f.lv[i] += s;
};
const auto add_l2_fix = [&](int i) -> void {
for (int t = v + 1 - i; t <= v; ++t)
if (t + (t & -t) <= v) {
f.lv[v + 1 - (t + (t & -t))] += f.lv[v + 1 - t];
}
};
m32 fs[65] = { 1 };
for (int i = 1; i <= pi[v]; ++i) {
const int p = primes[i];
i64 e_max = 1;
fs[1] = fpp(p, 1);
for (i64 M = divide(N, p); M >= p; M = divide(M, p), ++e_max) fs[e_max + 1] = fs[e_max] * fs[1];
i64 q = i64(p) * p;
for (i64 e = 2; e <= e_max; ++e, q *= p) {
const m32 d = fpp(p, e) - fs[e];
if (d == 0) continue;
for (i64 e2 = e_max; e2 >= e; --e2) fs[e2] += fs[e2 - e] * d;
const i64 L = N / q;
const int th_l = sqrt(L + 0.5), th_s = divide(L, th_l + 1);
int pq = divide(L, v / q + 1);
if (q <= v) {
for (int j = 1; j <= v / q; ++j) {
const i64 k = i64(j + 1) * q;
const m32 s = (k <= v) ? sum_l(k, j * q) : (sum_l(v + 1, j * q) + sum_s(pq, v));
add_l2(j, d * s);
}
}
for (int j = v / q + 1, nq = 0; j <= th_l; ++j, pq = nq)
add_l2(j, d * sum_s(nq = divide(L, j + 1), pq));
add_l2_fix(th_l);
int pq2 = 0, pk = v + 1;
for (int j = th_s, nq2 = 0; j >= 1; --j) {
const i64 k = i64(j) * q;
const m32 s = sum_s(j - 1, j);
if (k <= v) add_s(k, pk, d * s), pk = k;
else add_l(nq2 = divide(N, k), pq2, d * s), pq2 = nq2;
}
if (q <= v) add_s_fix(q, v);
if (pq2 > 0) add_l_fix(v + 1 - pq2, v);
}
}
for (int i = 1; i <= v; ++i)
if (i & (i - 1))
f.sv[i] += f.sv[i & (i - 1)];
s_sum = f.sv[v];
for (int i = 1; i <= v; ++i) {
if (i & (i - 1)) f.lv[v + 1 - i] += f.lv[v + 1 - (i & (i - 1))];
else f.lv[v + 1 - i] += s_sum;
}
return f;
};
block l0 = calc_large([&](u64 n) { return 1; }, [&](u64 n) { return m32(n % mod); });
block l1 = calc_large([&](u64 n) { return m32(n % mod); }, [&](u64 n) { return n %= mod, m32(n * (n + 1) / 2 % mod); });
for (int i = 1; i <= v; ++i) l1.lv[i] = A * l0.lv[i] + B * l1.lv[i], l1.sv[i] = 0;
auto fp = [&](u32 p) { return A + B * p; };
auto fpp = [&](u32 p, u32 e) { return A * e + B * p; };
return mult_powerful(attach_small(mult_large(calc_medium(fp), l1), fp), fpp);
}
signed main() {
i64 T, n;
m32 A, B;
while (T--) {
cin >> n >> A.x >> B.x;
block f = solve(n, A, B);
vector<m32> res(f.sv.begin() + 1, f.sv.end());
res.insert(res.end(), f.lv.begin() + 1, f.lv.end());
sort(res.begin(), res.end(), [](const m32 a, const m32 b) { return a.x < b.x; });
res.erase(unique(res.begin(), res.end()), res.end());
u32 ans = 0;
for (auto x : res) ans ^= x.x;
cout << ans << endl;
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Wrong Answer
time: 0ms
memory: 3712kb
input:
10000 988 56395756 60780067 7923 293552717 438195956 4847 24236686 75287211 6694 74889751 64994726 3720 385482711 188638093 6021 2928896 248853035 6808 310612405 330739724 4062 15289930 175596707 9583 56394035 335888448 9798 151396947 371306315 4365 216662501 351771943 1359 165179730 80942360 1436 3...
output:
result:
wrong answer Answer contains longer sequence [length = 10000], but output contains 0 elements