【BZOJ】3994: [SDOI2015]约数个数和

题意:

(T(1 le T le 50000))次询问,每次给出(n, m(1 le n, m le 50000)),求(sum_{i=1}^{n} sum_{j=1}^{m} d(ij)),其中(d(n))表示(n)的约数个数

分析

有个结论:

$$sum_{x_1}^{y_1} sum_{x_2}^{y_2} cdots sum_{x_k}^{y_k} d(x_1 x_2 cdots x_k) = sum_{x_1}^{y_1} sum_{x_2}^{y_2} cdots sum_{x_k}^{y_k} prod_{i=1}^{k} left lfloor frac{y_i}{x_i} ight floor prod_{i < j } [(x_i, x_j)=1]$$

(证明是二大重数学归纳,数学恐惧症的快快离开。
首先对于(k=1),我们可以通过算贡献证明。现在我们对(k>1)进行归纳:
我们需要证明:$$d_1(y_1, y_2, cdots, y_k) = sum_{x_1}^{y_1} sum_{x_2}^{y_2} cdots sum_{x_k}^{y_k} d(x_1 x_2 cdots x_k) = f_1 (y_1, y_2, cdots, y_k) = sum_{x_1}^{y_1} sum_{x_2}^{y_2} cdots sum_{x_k}^{y_k} prod_{i=1}^{k} left lfloor frac{y_i}{x_i} ight floor prod_{i < j} [(x_i, x_j)=1]$$
我们通过(y_1)来归纳:
首先(y_1=1)时,发现就是(k-1)维的证明,根据归纳条件,成立。
然后对于(y_1 > 1),我们设$$d_2(y_1, y_2, cdots, y_k) = d_1(y_1, y_2, cdots, y_k) - d_1(y_1-1, y_2, cdots, y_k)$$ $$f_2(y_1, y_2, cdots, y_k) = f_1(y_1, y_2, cdots, y_k) - f_1(y_1-1, y_2, cdots, y_k)$$然后用(y_2)归纳(d_2 = f_2)。一直这样做下去,直到需要归纳(d_{k+1} = f_{k+1})
就是需要证明这个结论:

[d_{k+1}(y_1, y_2, cdots, y_k) = d(y_1 y_2 cdots y_k) = f_{k+1}(y_1, y_2, cdots, y_k) = sum_{x_1|y_1} sum_{x_2|y_2} cdots sum_{x_k|y_k} prod_{i < j} [(x_i, x_j)=1] ]

这个结论通过讨论质因子的贡献就能证明出。

题解

于是剩下的不多说,分块大法。

$$ egin{align} ans & = sum_{i=1}^{n} sum_{j=1}^{m} d(ij) \

& =
sum_{i=1}^{n}
sum_{j=1}^{m} left lfloor frac{n}{i} ight floor left lfloor frac{m}{j} ight floor [(i, j)=1]

& =
sum_{d=1}^{n} mu(d)
sum_{i=1}^{ left lfloor frac{n}{d} ight floor }
sum_{j=1}^{ left lfloor frac{m}{d} ight floor } left lfloor frac{n}{id} ight floor left lfloor frac{m}{jd} ight floor

& =
sum_{d=1}^{n} mu(d)
sum_{i=1}^{ left lfloor frac{n}{d} ight floor } left lfloor frac{ left lfloor frac{n}{d} ight floor }{i} ight floor
sum_{j=1}^{ left lfloor frac{m}{d} ight floor } left lfloor frac{ left lfloor frac{m}{d} ight floor }{j} ight floor

end{align}

[</p> 我们用$O(n^{1.5})$预处理$d(n) = sum_{i=1}^{n} left lfloor frac{n}{i} ight floor$,然后就解决拉(其实是可以乱搞一下然后用线性筛筛的) #include <bits/stdc++.h> using namespace std; typedef long long ll; const int Lim=50000, N=50005; int p[N], np[N], pcnt, mu[N]; ll d[N]; void init() { mu[1]=1; for(int i=2; i<=Lim; ++i) { if(!np[i]) { p[pcnt++]=i; mu[i]=-1; } for(int j=0; j<pcnt; ++j) { int t=p[j]*i; if(t>Lim) break; np[t]=1; if(i%p[j]==0) break; mu[t]=-mu[i]; } } for(int n=1; n<=Lim; ++n) { for(int i=1, pos=1; i<=n; i=pos+1) { pos=n/(n/i); d[n]+=(ll)(pos-i+1)*(n/i); } mu[n]+=mu[n-1]; } } void work() { int n, m; ll ans=0; scanf("%d%d", &n, &m); if(n>m) { swap(n, m); } for(int i=1, pos=1; i<=n; i=pos+1) { pos=min(n/(n/i), m/(m/i)); ans+=(ll)(mu[pos]-mu[i-1])*d[n/i]*d[m/i]; } printf("%lld ", ans); } int main() { int T; scanf("%d", &T); init(); while(T--) { work(); } return 0; }]

原文地址:https://www.cnblogs.com/iwtwiioi/p/4986325.html