zoukankan      html  css  js  c++  java
  • BZOJ 3994: [SDOI2015]约数个数和 [莫比乌斯反演 转化]

    2015

    题意:(d(i))为i的约数个数,求(sumlimits_{i=1}^n sumlimits_{j=1}^m d(ij))


    (ij)都爆int了....
    一开始想容斥一下用(d(i))(d(j))(d(ij)),发现不行...
    然后翻题解看到了一步好神的转化:

    [d(nm) = sum_{imid n} sum_{jmid m} [gcd(i,j)=1] ]

    晚上再补吧还是没拿草稿纸...


    补:
    (Proof.)

    • 首先注意约数个数 相同的算一个
      约数个数公式(prod (a_i+1))
      考虑一个质因子,(p^x,p^y ightarrow p^x p^y)
      (x+y+1)对应了(gcd(p^x, 1)...gcd(1, 1)...gcd(1,p^y))
      质因子相互独立,乘起来

    然后愉♂悦的套路推♂倒

    [egin{align*} sum_{i=1}^n sum_{j=1}^m d(ij) &= sum_{i=1}^n sum_{j=1}^m sum_{xmid i} sum_{ymid j} [gcd(x,y)=1]\ 先枚举约数,交换i,j x,y\ &=sum_{i=1}^n sum_{j=1}^m sum_{dmid i,dmid j}mu(d) frac{n}{i} frac{m}{i}\ &=sum_{d=1}^n mu(d)sum_{i=1}^frac{n}{i} sum_{j=1}^frac{m}{i} frac{n}{id}frac{m}{jd}\ &=sum_{d=1}^n mu(d) f(frac{n}{id})f(frac{m}{jd})\ end{align*} ]

    问题就是(f(n)=sum_{i=1}^nfrac{n}{i})怎么求了
    可以n根n预处理...
    更巧妙的做法是,发现(f)就是(d)的前缀和,因为(frac{n}{i})表示的就是(1..n)有几个i的倍数

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=5e4+5;
    typedef long long ll;
    #define pii pair<int, int>
    #define MP make_pair
    #define fir first
    #define sec second
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
     
    int n, m;
    int notp[N], p[N], mu[N]; ll f[N]; pii lp[N];
    void sieve(int n) {
        mu[1] = 1; f[1] = 1;
        for(int i=2; i<=n; i++) {
            if(!notp[i]) p[++p[0]] = i, mu[i] = -1, f[i] = 2, lp[i] = MP(i, 1);
            for(int j=1; j<=p[0] && i*p[j]<=n; j++) {
                int t = i*p[j];
                notp[t] = 1;
                if(i%p[j] == 0) {
                    mu[t] = 0;
                    lp[t] = MP(p[j], lp[i].sec + 1);
                    f[t] = f[i] / (lp[i].sec + 1) * (lp[t].sec + 1);
                    break;
                }
                mu[t] = -mu[i];
                lp[t] = MP(p[j], 1);
                f[t] = f[i] * (lp[t].sec + 1);
            }
        }
        for(int i=1; i<=n; i++) mu[i] += mu[i-1], f[i] += f[i-1];
    }
    ll cal(int n, int m) {
        ll ans=0; int r;
        for(int i=1; i<=n; i=r+1) {
            r = min(n/(n/i), m/(m/i)); 
            ans += (mu[r] - mu[i-1]) * f[n/i] * f[m/i];
        }
        return ans;
    }
    int main() {
        //freopen("in","r",stdin);
        sieve(N-1);
        int T=read();
        while(T--){
            n=read(); m=read();
            if(n>m) swap(n, m);
            printf("%lld
    ",cal(n, m));
        }
    }
    
  • 相关阅读:
    155. 最小栈
    160. 相交链表
    PAT 1057 Stack
    PAT 1026 Table Tennis
    PAT 1017 Queueing at Bank
    PAT 1014 Waiting in Line
    PAT 1029 Median
    PAT 1016 Phone Bills
    PAT 1010 Radix
    PAT 1122 Hamiltonian Cycle
  • 原文地址:https://www.cnblogs.com/candy99/p/6611672.html
Copyright © 2011-2022 走看看