Luo Gu P5221 Product Euler's theorem Euler function +

Luo Gu P5221 Product

label

  • Euler function
  • Euler's theorem

Foreword

  • no

Concise meaning of the questions

  • 求:
    \[\prod_{i=1}^n\prod_{j=1}^n\frac {lcm(i,j)}{gcd(i,j)}(\%104857601)\]
  • Data range is 1e6, time is 0.2s

Thinking

  • Original formula \ (LCM \) a \ (GCD \) represents, therefore the original formula:
    \ [\ prod_. 1} ^ {n-I = \ J = prod_. 1} ^ {n-\ ij of FRAC {} {\ left ( gcd (i, j) \ right ) ^ 2} \]

    Generally, \ (LCM \) is not \ (GCD \) as apparent recursive, so \ (LCM \) not determined directly, will usually \ (\ LCM) is converted into \ (GCD \) to seek \ (LCM \) , and \ (GCD (I, J) * LCM (I, J) = ij of \) , so \ (lcm (i, j) = \ frac {ij} {gcd (i, j)} \)

  • Using open associativity:
    \ [\ prod_. 1} ^ {n-I = \ {prod_ J = NIJ. 1} ^ * \ left (\ prod_. 1} ^ {n-I = \ prod_. 1} = {J ^ ngcd (I , j) \ right) ^ { - 2} \]

    Accumulate / multiply formula satisfy such properties :( associativity)
    \ [\ sum_ {I} (a_i + B_i) = \ sum_ia_i + \ sum_ib_i \]
    \ [\ prod_ {I} (a_i + B_i) = \ prod_ia_i * \ prod_ib_i \]

    Note that, on multiple and style: in \ (\ \ sum) have in
    \ [\ sum \ limits_ia_i \ sum
    \ limits_jb_j = \ sum \ limits_ia_i * \ sum \ limits_jb_j \] in \ (\ prod \) in
    \ [\ prod \ limits_ia_i \ prod \ limits_j ^
    nb_j = \ prod \ limits_ia_i * \ left (\ prod \ limits_jb_j \ right) ^ n \] Therefore, when multiplied by the number of summed symbols, \ (\ SUM \) in the multiplication can be omitted in \ (\ prod \) remember not to omit the multiplication sign in

    Topic: allocation ratio:
    \ [\ sum_ika_i = K \ sum_ia_i \]
    \ [\ prod_i nka_i ^ = n-K * ^ \ ^ n-prod_i a_i, and \]

    Distribution rate is to be mentioned preceded by \ riding type in the number

  • 先求\(\prod\limits_{i=1}^n\prod\limits_{j=1}^nij\)。直接分配律得:
    \[\prod\limits_{i=1}^n\left(i^n*\prod\limits_{j=1}^nj\right)=\prod\limits_{i=1}^n\left(i^n*n!\right)=(n!)^n*\prod_{i=1}^ni^n=(n!)^n*(n!)^n=(n!)^{2n}\]
  • The first equation to solve this way, we now to seek a second equation: \ (\ Prod \ limits_. 1} ^ {n-I = \ Prod \ limits_. 1} = {J ^ ngcd (I, J) \ ) , first to enumerate \ (GCD \) , then to the power value at the number of occurrences:
    \ [\ prod_. 1 = {X} ^ {^ NX \ sum_. 1} ^ {n-I = \ sum_ { j = 1} ^ n [gcd (i, j) == x]} \]
  • Behind \ (\ sum \ limits_ {i = 1} ^ n \ sum \ limits_ {j = 1} ^ n [gcd (i, j) == x] \) is not familiar? He is equivalent to \ (2pre \ Phi ([\ FRAC NX]) - 1 \) (Euler function here introduced to the students is not clear to double me. Euler function of the article under the classification of an article talked about ), so the second equation equal to:
    \ [\ prod_. 1 = {X} ^ {^ NX 2pre \ Phi ([\ NX FRAC]) -. 1} \]
  • Thus the total formula is required:
    \ [(n-!)} ^ {2N * \ left (\ prod_. 1 = {X} ^ {^ NX 2pre \ Phi ([\ NX FRAC]) -. 1} \ right) ^ {-2}\]
  • The left side of the equation rapid power \ (O (nlogn) \) will be able to deal with it, the right of the screen and then can advance linear prefix and out \ (2pre \ Phi ([\ FRAC NX]) - 1 \) , seeking out find the right formula to give a multiplicative inverse, we will be able to find the answer.
  • Note that here \ (x \) is part of our index is saved up an array, but also to preserve the value should be the true value rather than modulo, because the index is not modulo! ! Do not be confused.
  • So, the real value of the index is more than int, we can only open a longlong save index, subject only to the 7.8MB of memory, 1kb about int = 250, a hand count will find no less than longlong open. Therefore, we need to also take die on the index. How modulo? Euler's theorem, as long as the modulus is a prime number, meaning power calculation in the mold, you can advance to th% on the modulus of the Euler function, which is the modulus -1, then the AC will be able to.

Precautions

to sum up

  • Generally, \ (LCM \) is not \ (GCD \) as apparent recursive, so \ (LCM \) not determined directly, will usually \ (\ LCM) is converted into \ (GCD \) to seek \ (LCM \) , and \ (GCD (I, J) * LCM (I, J) = ij of \) , so \ (lcm (i, j) = \ frac {ij} {gcd (i, j)} \)
  • Law operator Summary:

    Accumulate / multiply formula satisfy such properties :( associativity)
    \ [\ sum_ {I} (a_i + B_i) = \ sum_ia_i + \ sum_ib_i \]
    \ [\ prod_ {I} (a_i + B_i) = \ prod_ia_i * \ prod_ib_i \]

    Note that, on multiple and style: in \ (\ \ sum) have in
    \ [\ sum \ limits_ia_i \ sum
    \ limits_jb_j = \ sum \ limits_ia_i * \ sum \ limits_jb_j \] in \ (\ prod \) in
    \ [\ prod \ limits_ia_i \ prod \ limits_j ^
    nb_j = \ prod \ limits_ia_i * \ left (\ prod \ limits_jb_j \ right) ^ n \] Therefore, when multiplied by the number of summed symbols, \ (\ SUM \) in the multiplication can be omitted in \ (\ prod \) remember not to omit the multiplication sign in

    Topic: allocation ratio:
    \ [\ sum_ika_i = K \ sum_ia_i \]
    \ [\ prod_i nka_i ^ = n-K * ^ \ ^ n-prod_i a_i, and \]

    Distribution rate is to be mentioned preceded by \ riding type in the number

  • Note that an inverse element calculation for \ (\ FRAC ab & \ INV% P = A * (B \% P) \% P \) , the inverse number is calculated modulo advance! ! !
  • \ (A ^ b \% p \) , A mod p when the operation can advance, but is totally unacceptable in advance b modulo p, but should use Euler's theorem.

AC Code

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 1e6 + 10;
const int mod = 104857601;

bool no_prime[maxn];
int prime[maxn], 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++)
        phi[i] = (phi[i - 1] + 2 * phi[i]) % (mod - 1);

    return cnt;
}

int ksm(int a, int b)
{
    int ans = 1, base = a;
    while (b)
    {
        if (b & 1)
            ans = 1ll * ans * base % mod;
        base = 1ll * base * base % mod;
        b >>= 1;
    }
    return ans;
}

void solve()
{
    int n;
    scanf("%d", &n);
    shai(n);

    int ans = 1;
    for (int i = 1; i <= n; i++)
        ans = 1ll * ans * i % mod;
    ans = ksm(ans, 2 * n);

    int tot = 1;
    for (int x = 1; x <= n; x++)
        tot = (1ll * tot * ksm(x, phi[n / x] - 1)) % mod;

    printf("%d", 1ll * ans * ksm(1ll * tot * tot % mod, mod - 2) % mod);
}

int main()
{
    solve();
    return 0;
}

Guess you like

Origin www.cnblogs.com/danzh/p/11309179.html