maomao90's Library
A C++20 library for competitive programming.
Loading...
Searching...
No Matches
multiplicative_function.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cassert>
4#include <concepts>
5#include <vector>
6
8
9namespace maomao90 {
10using namespace std;
11// sumg is a vector of size 2 * m where sumg[i] represents prefix sum of
12// g from 2 to i + 1 for i < m, otherwise, sum from 2 to n / (2 * m - i)
13// g is a function that returns the value of g(prime)
14// returns prefix sum of g at prime indices with the same range as sumg
15template <typename T, typename G>
16 requires requires(G g, long long prime) {
17 { g(prime) } -> same_as<T>;
20vector<T> lucy_dp(long long n, vector<T> sumg, G g) {
21 assert(sumg.size() % 2 == 0);
22 long long m = sumg.size() / 2;
23 assert(m * m <= n && (m + 1) * (m + 1) > n);
24 vector<bool> is_prime(m + 1);
25 for (int i = 2; i <= m; i++) {
26 is_prime[i] = 1;
27 }
28 for (int i = 2; i * i <= m; i++) {
29 if (!is_prime[i]) {
30 continue;
31 }
32 for (int j = i * i; j <= m; j += i) {
33 is_prime[j] = 0;
34 }
35 }
36 vector<long long> div(m + 1);
37 vector<T> sumgp = sumg;
38 for (int i = 1; i <= m; i++) {
39 div[i] = n / i;
40 }
41 for (int prime = 2; prime <= m; prime++) {
42 if (!is_prime[prime]) {
43 continue;
44 }
45 long long prime_squared = (long long)prime * prime, iprime = prime;
46 for (int i = 1; i <= m; i++, iprime += prime) {
47 if (div[i] < prime_squared) {
48 break;
49 }
50 T div_val =
51 iprime <= m ? sumgp[2 * m - iprime] : sumgp[div[i] / prime - 1];
52 sumgp[2 * m - i] -= g(prime) * (div_val - sumgp[prime - 2]);
53 }
54 for (int i = m; i >= prime_squared; i--) {
55 sumgp[i - 1] -= g(prime) * (sumgp[i / prime - 1] - sumgp[prime - 2]);
56 }
57 }
58 return sumgp;
59}
60template <typename T, typename F>
61 requires requires(F f, long long prime, int power) {
62 { f(prime, power) } -> same_as<T>;
65vector<T> min25_sieve(long long n, vector<T> sumfp, F f) {
66 assert(sumfp.size() % 2 == 0);
67 long long m = sumfp.size() / 2;
68 assert(m * m <= n && (m + 1) * (m + 1) > n);
69 vector<bool> is_prime(m + 1);
70 for (int i = 2; i <= m; i++) {
71 is_prime[i] = 1;
72 }
73 for (int i = 2; i * i <= m; i++) {
74 if (!is_prime[i]) {
75 continue;
76 }
77 for (int j = i * i; j <= m; j += i) {
78 is_prime[j] = 0;
79 }
80 }
81 vector<long long> div(m + 1);
82 vector<T> sumf = sumfp, _sumf = sumf;
83 for (int i = 1; i <= m; i++) {
84 div[i] = n / i;
85 }
86 for (int prime = m; prime >= 2; prime--) {
87 if (!is_prime[prime]) {
88 continue;
89 }
90 int pow = 1;
91 for (long long prime_pow = prime; div[prime] >= prime_pow;
92 prime_pow *= prime, pow++) {
93 for (int i = 1; i <= m; i++) {
94 long long divprime = div[i] / prime_pow;
95 if (divprime < prime) {
96 break;
97 }
98 T div_val = i * prime_pow <= m ? sumf[2 * m - i * prime_pow]
99 : sumf[divprime - 1];
100 _sumf[2 * m - i] +=
101 f(prime, pow) * (div_val - sumfp[prime - 1]) + f(prime, pow + 1);
102 }
103 for (int i = m; i >= 1; i--) {
104 long long divprime = i / prime_pow;
105 if (divprime < prime) {
106 break;
107 }
108 _sumf[i - 1] += f(prime, pow) * (sumf[divprime - 1] - sumf[prime - 1]) +
109 f(prime, pow + 1);
110 }
111 }
112 long long prime_squared = (long long)prime * prime;
113 int lim =
114 prime_squared <= m ? prime_squared - 1 : 2 * m - n / prime_squared;
115 for (int i = 2 * m - 1; i >= lim; i--) {
116 sumf[i] = _sumf[i];
117 }
118 }
119 for (int i = 0; i < 2 * m; i++) {
120 sumf[i] += f(1, 0);
121 }
122 return sumf;
123}
124} // namespace maomao90
Definition concepts.hpp:19
Definition hashmap.hpp:8
vector< T > min25_sieve(long long n, vector< T > sumfp, F f)
Definition multiplicative_function.hpp:65
constexpr bool is_prime(T n)
Definition primality_test.hpp:44
vector< T > lucy_dp(long long n, vector< T > sumg, G g)
Definition multiplicative_function.hpp:20