Luo Gu P3768 simple math problems
label
- Mobius inversion
- Dirichlet convolution
- Du teach sieve
Foreword
- Very simple good push ~
Concise meaning of the questions
- Seeking
\ [\ sum_ {i = 1 } \ sum_ ^ ( mod p lower sense) nijgcd (i, j) ^ n {j = 1} \]
Thinking
- Very simple duck. Push down again on the out ~
\ [\ sum_. 1} ^ {n-I = \ sum_ {J} = ^ nijgcd. 1 (I, J) \] To enumerate GCD:
\ [\ sum_ = {X ^}. 1 NX \ sum_. 1} ^ {n-I = \ sum_. 1} = {J ^ NIJ [GCD (I, J) == X] \]They are routine ah! Doubly appearing in formulas \ (gcd (i, J) \) , then changed to enumerate
See the \ ([gcd (i, j ) == x] \) too familiar, but I say step by step. First replace enumeration limit:
\ [\ sum_. 1} = X ^ {^. 3 NX \ sum_. 1 = {I} ^ {[\ NX FRAC]} \ sum_. 1} = {J ^ {[\ NX FRAC]} ij of [gcd (i, j) == 1] \]Here briefly about why \ (the X-^ 3 \) . After replacing the cap because enumeration, enumeration that is the original \ (\ FRAC 1x \) , so ij have become old \ (\ FRAC 1x \) , so it should be multiplied by \ (the X-^ 2 \) , and then moved to the front is \ (x ^ 3 \) a
Then inversion duck, with \ (\ sum_ {d | n } \ mu (d) \) Alternatively \ ([GCD (I, J) ==. 1] \) , and the \ (d | gcd (i, j ) \) to \ (d | i and d | j \) to give:
\ [\ sum_. 1} = X ^ {^. 3 NX \ sum_. 1 = {I} ^ {[\ NX FRAC]} \ sum_ {J = 1} ^ {[\ frac nx]} ij \ sum_ {d | i and d | j} \ mu (d ) \]I remember the nature of the gcd: \ (d | gcd (i, J) \ IFF d | i and d | j \)
- Then the routine again, after the replacement to enumerate d, is then:
\ [\ sum_. 1} = X ^ {^. 3 NX \ sum_. 1 = {D} ^ {[\ NX FRAC]} \ MU ( d) \ sum_ {i = 1 } ^ {[\ frac nx]} \ sum_ {j = 1} ^ {[\ frac nx]} ij [d | i and d | j] \] - Then see \ ([d | i and d | j] \) we could not help but change with the upper limit of the enumeration, remember to change the upper limit, the number of enumeration became the original \ (\ frac 1d \) , it should take back:
\ [\ sum_ {X =. 1} ^ NX ^. 3 \ sum_ {D =. 1} ^ {[\ FRAC NX]} \ MU (D) \ sum_ {I =. 1} ^ {[\ frac n {dx}]} \ sum_ {j = 1} ^ {[\ frac n {dx}]} ijd ^ 2 \] Primary oersted tells us \ (G (X) = \ SUM \ limits_ {I =. 1} ^ X \ SUM \ limits_ {J =. 1} ^ xij = X ^ 2 * (X +. 1) ^ 2 /. 4 \) , so the original formula is actually seeking:
\ [\ sum_ {X =. 1} ^ n-\ sum_ {D =. 1} ^ {[\ FRAC NX]} \ MU (D) G ([\ FRAC n-{DX}]) D ^ 2x ^ 3 \]The above equation is the primary Mathematical Olympiad joke. It is actually derived: \ (G (X) = \ SUM \ limits_. 1} ^ {X = I \ SUM \ limits_ J = {xij. 1} ^ = \ SUM \ limits_. 1} = {I ^ XI \ SUM \ limits_ {i = 1} ^ xi = (n * (n + 1) / 2) ^ 2 \)
A look at this time, the upper limit of the relationship between x and d, found enumeration can be replaced, instead we enumerate \ (DX = K \) , then the original formula is:
\ [\ sum_. 1} ^ {K = NK ^ 2g ([\ frac nk] ) \ sum_ {d | k} \ mu (\ frac kd) d \]This step was changed to enumerate how \ (K = dx \) and do not know the students look at my blog "number theory formula summary" poke here
- Obviously \ (\ sum \ limits_ {d | k} \ mu (\ frac kd) d \) is \ (\ mu and id \) of the Dirichlet convolution duck! Well known \ (\ MU ID = * \ Phi \) , we find the actual:
\ [\ sum_ K = {}. 1 NK ^ ^ 2 \ Phi (K) G ([\ FRAC NK]) \] Here's a look inside the g \ (\ FRAC NK \) , you know you want to block the oh ~ so we need to find \ (k ^ 2 \ mu ( k) \) prefix and violence is clearly not enough, so we teach Du sieve chant, so the question now is how to teach Du screen
- Is now required \ (x ^ 2 \ phi ( x) \) prefix and, we set \ (F (X) = X ^ 2 \ Phi (X) \) , find a function \ (g (x) \) , then Du teach sift:
\ [S (n-) G (. 1) = \ sum_ {I}. 1 ^ = NF * G- \ sum_ {2} = I ^ ng (I) S ([\ Ni FRAC ]) \] - In fact, when Du teach sieve find \ (g (x) \) , they often pay more attention \ (f * g \) prefix and good demand of Dirichlet convolution, usually both convolution is \ (\ Epsilon \) or \ (ID \) or \ (\ Phi (n-) \) . So now a need to find \ (G (X) \) , such that \ (f * g \) is \ (\ Epsilon \) or \ (ID \) . We write the convolution of both:
\ [(F * G) (n-) = \ sum_ {D |} n-F (D) G ([\ FRAC Nd]) \] - We \ (f (x) = x ^ 2 \ phi (x) \) with in, derived \ (F \) and \ (G \) convolution is:
\ [(F * G) (n-) = \ sum_ {d | n} d ^ 2 \ phi (d) g ([\ frac nd]) \] To here, it is not very easy to determine \ (g \) do? If so \ (G = ID \) , will find \ (d ^ 2 \) is got of Jesus. Then \ (F \) and \ (G \) convolution is:
\ [(F * G) (n-) = \ sum_ {D | D ^ n-2} \ Phi (D) \ FRAC Nd \ Nd = FRAC \ sum_ {d | n} \ phi (d) n ^ 2 = n ^ 2 \ sum_ {d | n} \ phi (d) = n ^ 3 \]\ (\ SUM \ limits_ {D | n-} = \ Phi (D) = D \) , to give about n-number to obtain a sum of the Euler function is n, which is commonly used conclusion! ! !
Du convolution into the above teachings sieve, can be obtained:
\ [S (n-) = \ sum_ {I}. 1 = 3- ^ Ni ^ \ sum_ {2} = I ^ ng (I) S ([\ frac ni]) \]From primary Mathematical Olympiad can \ (O (1) \) to obtain \ (i ^ 3 \) prefix and then sieve Du teach written on it A! !
Precautions
- In the calculation of \ (i ^ 3, i ^ 2 \) prefix and will overflow to count the multiplicative inverse. Further, \ (I \) may be larger than the modulus, the modulo should first recalculation
to sum up
- In fact, when Du teach sieve find \ (g (x) \) , they often pay more attention \ (f * g \) prefix and good demand of Dirichlet convolution, usually both convolution is \ (\ epsilon \) or \ (the above mentioned id \) . So now a need to find \ (G (X) \) , such that \ (f * g \) is \ (\ Epsilon \) or \ (ID \) . Common Dirichlet convolution see my other blog post stamp here
- Summarizes several summation formula:
\ [\ sum_. 1 = {I}. 3 ^ Ni ^ = \ sum_. 1} ^ {n-I = \ sum_. 1} = {J ^ NIJ = \ left (\ {n-FRAC (N- . 1)} 2 \ right) ^ 2 \]
\ [\ sum_ = {I}. 1 ^ Ni ^ 2 = \ {n-FRAC (n-+. 1) (2N +. 1)}. 6 \]
AC Code
#include<cstdio>
#include<unordered_map>
using namespace std;
const int maxn = 1e7 + 10;
long long n;
int mod;
unordered_map<long long, int> rec;
int ksm(int a, int b)
{
int ans = 1, base = a % mod;
while (b)
{
if (b & 1)
ans = 1ll * ans * base % mod;
base = 1ll * base * base % mod;
b >>= 1;
}
return ans;
}
bool no_prime[maxn];
int prime[maxn], phi[maxn], pre_phi[maxn];
int shai(int n)
{
int cnt = 0;
phi[1] = 1;
for (int i = 2; i <= n; i++)
{
if (!no_prime[i])
prime[++cnt] = i, phi[i] = i - 1;
for (int j = 1; j <= cnt && prime[j] * i <= n; j++)
{
no_prime[prime[j] * i] = 1;
phi[prime[j] * i] = i % prime[j] == 0 ? phi[i] * prime[j] : phi[i] * (prime[j] - 1);
if (i % prime[j] == 0) break;
}
}
for (int i = 1; i <= n; i++)
pre_phi[i] = (pre_phi[i - 1] + 1ll * phi[i] * i % mod * i) % mod;
return cnt;
}
int inv2;
int inv6;
int pre_x2(long long n)
{
n %= mod;
return n * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod;
}
int pre_x3(long long n)
{
n %= mod;
return (n * (n + 1) % mod * inv2 % mod) * (n * (n + 1) % mod * inv2 % mod) % mod;
}
int S(long long n)
{
if (n <= maxn - 10) return pre_phi[n];
if (rec[n]) return rec[n];
int ans = pre_x3(n);
long long l = 2, r;
while (l <= n)
{
r = n / (n / l);
ans = (ans - (pre_x2(r) - pre_x2(l - 1)) * 1ll * S(n / l)) % mod;
l = r + 1;
}
return rec[n] = ans;
}
void solve()
{
scanf("%d%lld", &mod, &n);
shai(maxn - 10);
inv2 = ksm(2, mod - 2);
inv6 = ksm(6, mod - 2);
long long l = 1, r;
int ans = 0;
while (l <= n)
{
r = n / (n / l);
int gg = (S(r) - S(l - 1));
ans = (ans + 1ll * (S(r) - S(l - 1)) * 1ll * pre_x3(n / l)) % mod;
l = r + 1;
//printf("%d\n", gg);
}
printf("%d", (ans % mod + mod) % mod);
}
int main()
{
solve();
return 0;
}