Luo Valley P3312 [SDOI2014] + number table Mobius inversion segment tree and mesh number of about +


Luo Valley P3327 [SDOI2015] and the number of divisors
****
### tab

  • Mobius inversion
  • Block divisible
  • Linear sieve
    ****
    ### Foreword
  • Where the block is divisible another common form. I did a long time to figure out how to divide a long time after suddenly realized ..
    ****
    ### concise meaning of the questions
  • $ d (x) $ represents the number of $ X $ divisor. Given $ n, m $, seeking
    $$ \ sum_. 1} ^ {n-I = \ sum_ ^ {J}. 1 MD = (I J) $$
    ***
    ### ideas
  • First we should know that such a commonly used formula:
    $$ D (I * J) = \ sum_ {X | I} \ sum_ {Y | J} [GCD (X, Y) ==. 1] $$

    Remember this formula like

  • We calculate $ d (i, j) $ use this formula, the formula is equal to the original obtained:
    $$ \ sum_. 1} ^ {n-I = \ sum_. 1} = {J ^ MD (ij of) = \ {I = sum_ 1} ^ n \ sum_ {j = 1} ^ m \ sum_ {x | i} \ sum_ {y | j} [gcd (x, y) == 1] $$
  • $ x, y $ a $ i, j $ factor, factor calculation complexity is too violent, we enumerate the $ x, y $, $ n-apparent, about the maximum number m, respectively, does not exceed $ $ n, m $, and therefore, the original formula becomes:
    $$ \ sum_. 1} = X ^ {n-\ sum_ ^ {Y}. 1 m = \ left ([\ NX FRAC] [\ My FRAC] [GCD (X, Y) = = 1] \ right) $$
  • For $ [gcd (x, y) == 1] $ we can think quickly replaced with a function of the nature of Mobius $ \ sum \ limits_ {d | gcd (i, j)} \ mu (d) $, and have such property: $ d | gcd (i, j) \ iff d | i and d | j $ then it would be:
    $$ \ sum_. 1} ^ {n-I = \ sum_ {J} = ^. 1 m \ left ([\ frac ni ] [\ frac mj] \ sum \ limits_ {d | i and d | j} \ mu (d ) \ right) $$
  • Can be changed after the change enumeration $ d $, $ d $ $ as a divisor of n-$, $ D $ is obviously an upper limit of $ n $. It would be:
    $$ \ sum_. 1} ^ {n-D = \ MU (D) \ sum_. 1} ^ {n-I = \ sum_ {J}. 1 ^ m = \ left ([D | I and d | j] [\ FRAC Ni] [\ FRAC MJ] \ right) $$
  • 又有
    $$\sum\limits_{i=1}^n\sum\limits_{j=1}^m\left([d|i且d|j][\frac ni][\frac mj]\right)=\sum\limits_{i=1}^{[\frac nd]}\sum\limits_{j=1}^{[\frac md]}[\frac n{id}]*[\frac m{jd}]$$

    Derivation: we can find, $ \ sum \ limits_ {i = 1} ^ n \ sum \ limits_ {j = 1} ^ m [d | i and d | j] $, practical and effective tuple $ (i, j) $, with $ \ sum \ limits_ {i = 1} ^ {[\ frac nd]} \ sum \ limits_ {j = 1} ^ {[\ frac md]} $ $ enumerated tuple ( i, j) $ in number as much. In value, size of the former to the latter tuple $ D $ times. Therefore, after conversion limit, $ i, j $ became the original $ \ frac 1d $, we have to take them on $ d $ on the back to the original item.

  • Next, the original formula becomes:
    $$ \ sum_. 1} ^ {n-D = \ MU (D) \ SUM \ limits_. 1 = {I} ^ {[\ FRAC Nd]} \ SUM \ = J {limits_ 1} ^ {[\ frac md ]} [\ frac n {id}] * [\ frac m {jd}] $$
  • This time, for the latter equation $ \ sum \ limits_ {i = 1} ^ {[\ frac nd]} \ sum \ limits_ {j = 1} ^ {[\ frac md]} [\ frac n {id} ] * [\ frac m {jd }] $ can obviously be multiplied by transpose into two: $ \ sum \ limits_ {i = 1} ^ {[\ frac nd]} [\ frac n {id}] \ sum \ limits_ {j = 1 } ^ {[\ frac md]} [\ frac m {jd}] $, then it would be the original formula:
    $$ \ sum_. 1} ^ {n-D = \ MU (D) \ sum \ limits_ {i = 1 } ^ {[\ frac nd]} [\ frac n {id}] \ sum \ limits_ {j = 1} ^ {[\ frac md]} [\ frac m {jd}] $$
  • It is observed here $ \ sum \ limits_ {i = 1} ^ {[\ frac nd]} [\ frac n {id}] \ sum \ limits_ {j = 1} ^ {[\ frac md]} [\ frac m { jd}] $ is pretreated. There is a little difficult, where the unknown is both the $ D $, there $ n, m $, pretreatment need to enumerate $ d, n, m $, that would mean that the complexity of $ O (n ^ 3) $ the? We should abandon this idea, thinking can not stereotype. First, we do not need to directly $ \ sum \ limits_ {i = 1} ^ {[\ frac nd]} [\ frac n {id}] \ sum \ limits_ {j = 1} ^ {[\ frac md]} [\ frac m {jd}] $ formula whole pretreatment may be separated for $ \ sum \ limits_ {i = 1} ^ {[\ frac nd]} [\ frac n {id}] $ and $ \ SUM \ limits_ {j = 1} ^ {[\ frac md]} [\ frac m {jd}] $ pretreatment, so now enumerable and can be reduced to $ d, m $ two kinds of complexity $ O ( n ^ 2) $. But now observe, $ nd $-style house is in the whole a whole, they are a whole range of values ​​is determined. Can be enumerated directly $ \ frac nd $, thus pretreated complexity is $ O (n \ sqrt n) $, the total complexity is: $ O (n \ sqrt n + n * T) $.
  • However, there is less complex method, we let $ f (x) = \ sum \ limits_ {i = 1} ^ x [\ frac xi] $, then the original formula becomes:
    $$ \ sum_ {D n-^. 1} = \ left (\ MU (D) F ([\ FRAC Nd]) F ([\ FRAC MD]) \ right) $$
  • any of $ f $ is out may be pretreated by the aforesaid, whereby $ O (1) $ query. However, it is noted here that $ [\ frac nd] $ and $ [\ frac md] $ is a block, i.e. for a $ [l, r] $, the interval $ [\ frac nd] $ and $ [\ frac md] $ is determined, that the range of f $ ([\ FRAC Nd]) f ([\ FRAC md]) $ is determined. So only use this section F $ ([\ FRAC Nd]) F ([\ FRAC MD]) multiplied by $ $ \ mu (d) $ section and can be, ultimately reducing the complexity of $ O (n \ sqrt n + \ sqrt {n} * T) $, this problem can be
  • In fact, you can also do a little optimization. Before we define $ f (x) = \ sum \ limits_ {i = 1} ^ x [\ frac xi] $, if the number on the good students can immediately find, $ f (x) $ is $ [1, x ] approximately $ number and the number, so we can actually a pre-screening line function $ D $, then the prefix and do it again. Such optimization will probably four times faster
    ****
    ### Note
    ****
    ### summary
  • For expression $ \ sum \ limits_ {i = 1} ^ n \ sum \ limits_ {j = 1} ^ m [d | i and d | j] $ is clear that it is equal to $ \ sum \ limits_ {i = 1} ^ {[\ FRAC Nd]} \ SUM \ limits_ {J =. 1} ^ {[\ FRAC MD]}. 1 = [\ FRAC Nd] [\ FRAC MD] $, and for $ \ sum \ limits_ {i = 1 } ^ n \ sum \ limits_ { j = 1 ^ m [d | i and D | J]} [\ FRAC Ni] [\ FRAC MJ] $, in fact, the upper limit of enumeration were replaced $ [\ frac nd ] $ and $ [\ frac md] $, we enumerate is that all $ [d | i and d | j] $ tuple $ [i, j] $ of $ \ frac 1d $ times. We then calculate $ [\ FRAC Ni] [\ FRAC MJ] $ $ ij of the time To enlarge $ $ $ D times, so in fact we calculate should be $ [\ n-FRAC {ID}] [\ m FRAC {jd}] $, so there:
    $$ \ SUM \ limits_. 1} ^ {n-I = \ SUM \ limits_. 1} = {J ^ m [D | I and D | J]
    [\ FRAC Ni] [\ FRAC MJ] = \ SUM \ limits_ {I =. 1} ^ {[\ FRAC Nd]} \ SUM \ limits_ {J =. 1} ^ {[\ FRAC MD]} [\ FRAC n-{ID}] [\ FRAC m {jd}] $$
  • For such formula
    $$ \ sum_ {i = 1} ^ n \ sum_ {j = 1} ^ mij = \ left (\ sum_ {i = 1} ^ ni \ right) * \ left (\ sum_ {j = complexity 1} ^ mj \ right) $$ this directly $ (n ^ 2) O $ is reduced to $ O (n) $
  • Block is divisible, the most classic process $ \ sum \ limits_ {i = 1} ^ n [\ frac xi] $. But there is another common form: $ \ sum \ limits_ {i = 1} ^ nf ([\ frac xi]) $, each block of the same $ [\ frac ni] $ is the same, the same can be $ k $ th, counted over $ k * f [\ frac xi] $
  • $ D $ sieve linear function, it is necessary to open an array $ num [i] $ $ I $ recording a minimum number of prime factors arise. Processing, if $ i% prime [j] == 0 $, i.e. containing factor minimum $ prime [j] $, $ num [i] $ should be updated to $ num [i] + 1 $ , otherwise , there is no description $ I $ prime factors $ prime [j] $, and $ prime [j] $ is a new minimum quality factor, so NUM [I * Prime [J]] =. 1 (error-prone here to remember !!!)
    ****
    ### AC Code
#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 50000 + 10;

bool no_prime[maxn];
int prime[maxn], mu[maxn], pre_mu[maxn], dd[maxn], num[maxn];
long long pre_dd[maxn];
int shai(int n)
{
   int cnt = 0;
   mu[1] = dd[1] = 1;

   for (int i = 2; i <= n; i++)
   {
       if (!no_prime[i])
           prime[++cnt] = i, mu[i] = -1, dd[i] = 2, num[i] = 1;

       for (int j = 1; j <= cnt && prime[j] * i <= n; j++)
       {
           no_prime[prime[j] * i] = 1;
           mu[prime[j] * i] = (i % prime[j] == 0) ? 0 : -mu[i];
           dd[prime[j] * i] = (i % prime[j] == 0) ? dd[i] / (num[i] + 1) * (num[i] + 2) : dd[i] * 2;
           num[prime[j] * i] = (i % prime[j] == 0) ? num[i] + 1 : 1;
           if (i % prime[j] == 0) break;
       }
   }

   for (int i = 1; i <= n; i++)
       pre_mu[i] = pre_mu[i - 1] + mu[i], pre_dd[i] = pre_dd[i - 1] + dd[i];
       
   return cnt;
}

long long cal2(int n, int m)
{
   int l = 1, r;
   long long ans = 0;
   while (l <= n)
   {
       r = min(n / (n / l), m / (m / l));
       ans += 1ll * (pre_mu[r] - pre_mu[l - 1]) * pre_dd[n / l] * pre_dd[m / l];
       l = r + 1;
   }
   return ans;
}

void solve()
{
   shai(maxn - 10);

   int t;
   scanf("%d", &t);
   while (t--)
   {
       int n, m;
       scanf("%d%d", &n, &m);
       if (n > m) swap(n, m);

       printf("%lld\n", cal2(n, m));
   }
}

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

Guess you like

Origin www.cnblogs.com/dzzzh/p/11294710.html