[SDOI2015]约数个数和

题目

传送门

尝试与思考

\[\sum_{i=1}^n\sum_{j=1}^md(ij) \]

考虑设 \(T=ij\),那么就有

\[\text{ans}\;=\;\sum_{T=1}^{nm}d(T)\sum_{i=1}^{\frac{T}{m}\le i\le n}[i|T] \]

然后,发现这个东西不可做了,这方法破产了...

考虑另外一种思路,由于我们有

\[d(ij)=\sum_{x|i}\sum_{y|j}[\gcd(x,y)=1] \]

那么这个式子就是

\[\begin{aligned} \text{ans}\;&=\;\sum_{i=1}^n\sum_{j=1}^m\sum_{x|i}\sum_{y|j}[\gcd(x,y)=1] \\ &=\;\sum_{x=1}^n\sum_{y=1}^m[\gcd(x,y)=1]\sum_{x|i}\sum_{y|j}1 \\ &=\;\sum_{x=1}^n\sum_{y=1}^m[\gcd(x,y)=1]\left\lfloor\frac{n}{x}\right\rfloor\left\lfloor\frac{m}{y}\right\rfloor \\ &=\;\sum_{i=1}^n\sum_{j=1}^m\left\lfloor\frac{n}{i}\right\rfloor\left\lfloor\frac{m}{j}\right\rfloor\sum_{x|i,x|j}\mu(x) \\ &=\;\sum_{x=1}^n\mu(x)\sum_{i=1}^{n/x}\sum_{j=1}^{m/x}\left\lfloor\frac{n}{ix}\right\rfloor\left\lfloor\frac{m}{jx}\right\rfloor \end{aligned} \]

我们令 \(G(T)=\sum_{i=1}^{T}\left\lfloor\frac{T}{i}\right\rfloor\),首先这个函数可以分块算,同时有

\[\begin{aligned} \text{ans}\;=\;\sum_{x=1}^n\mu(x) G(\left\lfloor\frac{n}{x}\right\rfloor)G(\left\lfloor\frac{m}{x}\right\rfloor) \end{aligned} \]

考虑将 \(G()\) 预处理出来,对于答案也分块算,那么总复杂度就是 \(\mathcal O(n\sqrt n+T\sqrt n)\).

代码

# include <cstdio>
# include <algorithm>
using namespace std;
namespace Elaina{
    # define rep(i,l,r) for(int i=l, i##_end_ = r; i <= i##_end_; ++ i)
    # define fep(i,l,r) for(int i=l, i##_end_ = r; i >= i##_end_; -- i)
    # define fi first
    # define se second
    # define Endl putchar('\n')
    # define writc(x, c) fwrit(x), putchar(c)
    // # define int long long
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef unsigned long long ull;
    typedef unsigned int uint;
    template<class T>inline T Max(const T x, const T y){return x < y ? y : x;}
    template<class T>inline T Min(const T x, const T y){return x < y ? x : y;}
    template<class T>inline T fab(const T x){return x < 0 ? -x : x;}
    template<class T>inline void getMax(T& x, const T y){x = Max(x, y);}
    template<class T>inline void getMin(T& x, const T y){x = Min(x, y);}
    template<class T>T gcd(const T x, const T y){return y ? gcd(y, x % y) : x;}
    template<class T>inline T readin(T x){
        x=0; int f = 0; char c;
        while((c = getchar()) < '0' || '9' < c) if(c == '-') f = 1;
        for(x = (c ^ 48); '0' <= (c = getchar()) && c <= '9'; x = (x << 1) + (x << 3) + (c ^ 48));
        return f ? -x : x;
    }
    template<class T>void fwrit(const T x){
        if(x < 0)return putchar('-'), fwrit(-x);
        if(x > 9)fwrit(x / 10); putchar(x % 10 ^ 48);
    }
}
using namespace Elaina;

const int maxn = 50000;

int prime[maxn + 5], pcnt;
int sie[maxn + 5], mu[maxn + 5];
ll pre[maxn + 5];
inline void sieve(){
    mu[1] = pre[1] = 1;
    rep(i, 2, maxn){
        if(!sie[i]) prime[++ pcnt] = i, mu[i] = -1;
        for(int j = 1; j <= pcnt && i * prime[j] <= maxn; ++ j){
            sie[i * prime[j]] = 1;
            if(i % prime[j] == 0){
                mu[i * prime[j]] = 0; break;
            }
            mu[i * prime[j]] = -mu[i];
        }
        pre[i] = pre[i - 1] + mu[i];
    }
}

ll G[maxn + 5];

inline ll g(const int n){
    ll ret = 0;
    for(int l = 1, r; l <= n; l = r + 1){
        r = n / (n / l);
        ret += (r - l + 1) * (n / l);
    }
    return ret;
}

int n, m;

signed main(){
    sieve();
    rep(i, 1, maxn) G[i] = g(i);
    rep(cas, 1, readin(1)){
        n = readin(1), m = readin(1);
        if(n > m) swap(n, m);
        ll ans = 0;
        for(int l = 1, r; l <= n; l = r + 1){
            r = Min(n / (n / l), m / (m / l));
            ans += 1ll * (pre[r] - pre[l - 1]) * G[n / l] * G[m / l];
        }
        writc(ans, '\n');
    }
	return 0;
}

用到の一些trick

首当其冲的是这个结论

\[d(ij)=\sum_{x|i}\sum_{y|j}[\gcd(x,y)=1] \]

考虑怎么证明呢?我们设对于质数 \(p\)\(i\)\(a\) 个,\(j\)\(b\) 个,那么显然的,\(ij\) 就有 \(a+b\) 个,同时,在因子的选择上,\(ij\) 就有 \(a+b+1\) 中选择方案,而如果我们要保证 \(\gcd(x,y)=1\),那么对于 \(x,y\) 来说,最多只有一边会有 \(p\) 这个因子,那么对于只有 \(x\) 有的情况来说,有 \(a+1\) 种,对于只有 \(y\) 有的情况,就是 \(b+1\),同时还要减去重复算的两边都没有选择 \(x\) 的一种,就是 \(a+b+1+1-1=a+b+1\),所以这个可以等价.


其次,是 \(\gcd(x,y)=1\Leftrightarrow\sum_{i|x,i|y}\mu(i)=1\)

其实就是

\[\sum_{d|n}\mu(d)= \begin{cases} 1,n=1 \\ 0,n>1 \end{cases} \]

如果 \(n=1\),那么显然.

考虑对于其他情况,设 \(n=p_1^{a_1}..p_k^{a_k}\),那么在 \(n\) 的所有因子中,\(\mu\) 值不为零的只有所有质因子次数都为 \(1\) 的因子,其中质因数个数为 \(r\) 个的因子有 \({k\choose r}\) 个,那么就有

\[\begin{aligned} \sum_{d|n}\mu(d)&={k\choose 0}-{k\choose 1}+{k\choose 2}+...+(-1)^k{k\choose k} \\ &=\sum_{i=0}^k(-1)^i{k\choose i} \\ &=(1-1)^k=0 \end{aligned} \]

最后一步由二项式定理:

\[(x+y)^z=\sum_{i=0}^n{z\choose i}x^iy^{z-i} \]

给出.

posted @ 2021-01-09 17:41  Arextre  阅读(69)  评论(0编辑  收藏  举报