Luo Gu 2257: YY the GCD

Luo Gu 2257: YY the GCD

Description of the meaning of problems

  • Q \ (\ sum_. 1} = {I ^ N \ sum_. 1} = {J ^ M [GCD (I, J) == P] \) , where \ (P \) are all prime numbers.
  • Data range \ (N, M \. 7 Leq 10 ^ \) , there are \ (10000 \) set of test data.

Ideas:

  • Mobius inversion
  • Set \ (f (d) \) of \ (gcd (i, j) == d \) number: \ (F (D) = \ sum_. 1} ^ {n-I = \ sum_ = {J}. 1 m ^ [GCD (I, J) == D] \) .
  • \ (F (n) \) of \ (gcd (i, j) == kn \) number, where \ (K = 1,2, ... \) .
  • \(F(n)=\sum_{n|d}f(d)=\frac{N}{n}\frac{M}{n}\)
  • \(f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d)\)

  • \(ans=\sum_{p\in primes}\sum_{i=1}^N\sum_{j=1}^M[gcd(i,j)==p]\).

  • \(=\sum_{p\in primes}f(p)\)

  • \(=\sum_{p\in primes}\sum_{p|d}\mu(\frac{d}{p})F(d)\).

  • Enumeration \ (\ FRAC {P} = {D} T \) , there

  • \(=\sum_{p\in primes}\sum_{t=1}^{min\{\frac{N}{p},\frac{M}{p}\}}\mu(t)\frac{N}{tp}\frac{M}{tp}\)

  • Set \ (T = TP \) , are:

  • \(\sum_{p\in primes}\sum_{t=1}^{min\{\frac{N}{p},\frac{M}{p}\}}\mu(t)*\frac{N}{T}\frac{M}{T}\)

  • Enumerate what \ (T \) , are:

  • \(\sum_{T=1}^{min\{N,M\}}\frac{N}{T}\frac{M}{T}\sum_{k|T,k\in primes}\mu(\frac{T}{k})\)

  • This latter may be pretreated prefix and a summing \ (O (1) \) query.

  • Divisible by a preceding block may be optimized to \ (O (\ n-sqrt {}) \) .

  • #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e7 + 1e5;
    int mu[maxn], primes[maxn], cnt;
    long long sum[maxn], f[maxn];
    bool vis[maxn];
    void get_mu(int n)
    {
        mu[1] = 1;
        for(int i = 2; i <= n; i++)
        {
            if(!vis[i])
            {
                primes[++cnt] = i;
                mu[i] = -1;
            }
            for(int j = 1; primes[j] <= n/i; j++)
            {
                vis[primes[j]*i] = 1;
                if(i % primes[j] == 0) break;
                else mu[i*primes[j]] = -mu[i];
            }
        }
        for(int i = 1; i <= cnt; i++)
            for(int j = 1; primes[i] <= n/j; j++)
                f[j*primes[i]] += mu[j];
        for(int i = 1; i <= n; i++)
            sum[i] = sum[i-1] + f[i];
    }
    
    int main()
    {
        get_mu(10000000+5);
        int T; scanf("%d", &T);
        while(T--)
        {
            int n, m;
            long long ans = 0;
            scanf("%d%d", &n, &m);
            if(n > m) swap(n, m);
            for(int l = 1, r; l <= n; l = r+1)
            {
                r = min(n/(n/l), m/(m/l));
                ans += 1ll*(1ll*(n/l)*1ll*(m/l) * (sum[r]-sum[l-1]));
            }
            printf("%lld\n", ans);
        }
        return 0;
    }

Guess you like

Origin www.cnblogs.com/zxytxdy/p/12170596.html