zoukankan      html  css  js  c++  java
  • BZOJ 3994: [SDOI2015]约数个数和

    二次联通门 : BZOJ 3994: [SDOI2015]约数个数和

    $LARGE Answer =sum_{i=1}^{n}sum_{j=1}^{m}d(ij)$

               $LARGE = sum_{i=1}^{n}sum_{j=1}^{m}sum_{a|i}sum_{b|j}[gcd(a,b)=1]$

               $LARGE = sum_{i=1}^{n}sum_{j=1}^{m}lfloor dfrac{n}{i} floor lfloor dfrac{m}{j} floor [gcd(a,b)=1]$

               $LARGE = sum_{i=1}^{n}sum_{j=1}^{m}lfloor dfrac{n}{i} floor lfloor dfrac{m}{j} floor sum_{d|gcd(i,j)}mu(d)$

               $LARGE = sum_{d=1}^nmu(d)sum_{i=1}^{n/d}sum_{j=1}^{m/d}lfloor dfrac {n}{id} floor lfloor dfrac {m} {jd} floor$

               $LARGE = sum_{d=1}^nmu(d)sum_{i=1}^{n/d}sum_{j=1}^{m/d}lfloor dfrac {dfrac {n}{d}}{i} floor lfloor dfrac {dfrac {m}{d}} {j} floor$

    设 $LARGE f(n)=sum_{i=1}^{n} lfloor dfrac {n}{i} floor$

    代回原式得:

    $LARGE Answer =sum_{d=1}^nmu(d)f(dfrac nd) f(dfrac md)$

    /*
        BZOJ 3994: [SDOI2015]约数个数和
        
        莫比乌斯反演
    */
    #include <cstdio>
    #include <iostream>
    
    #define rg register
    inline void read (int &n)
    {
        rg char c = getchar ();
        for (n = 0; !isdigit (c); c = getchar ());
        for (; isdigit (c); n = n * 10 + c - '0', c = getchar ());
    }
    
    #define Max 50008
    int mu[Max], p[Max], sm[Max], f[Max]; bool is[Max];
    
    void Euler (int N)
    {
        int C = 0; rg int i, j, k; mu[1] = 1;
    
        for (i = 2; i <= N; ++ i)
        {
            if (!is[i]) p[++ C] = i, mu[i] = -1;
            for (j = 1; j <= C; ++ j)
            {
                k = i * p[j];
                if (k > N) break;
                is[k] = true;
                if (i % p[j] == 0) { mu[k] = 0; break; }
                else mu[k] = -mu[i];
            }
        }
        for (i = 1; i <= N; ++ i) sm[i] = sm[i - 1] + mu[i];
    }
    inline int min (int a, int b) { return a < b ? a : b; }
    int F (int N)
    {
        int res = 0;
        for (rg int i = 1, j; i <= N; i = j + 1)
            j = N / (N / i), res += (N / i) * (j - i + 1);
        return res;
    }
    typedef long long LL;
    #ifdef WIN32
    #define PLL "%I64d"
    #else
    #define PLL "%lld"
    #endif
    int main (int argc, char *argv[])
    {
        int T, N, M; read (T); rg int i, j; Euler (Max - 1);
    
        for (i = 1; i < Max; ++ i) f[i] = F (i);
        
        for (LL Answer; T; -- T)
        {
            read (N), read (M); Answer = 0;
            if (N > M) std :: swap (N, M);
                
            for (i = 1; i <= N; i = j + 1)
            {
                j = min (N / (N / i), M / (M / i));
                Answer += (LL) (sm[j] - sm[i - 1]) * f[N / i] * f[M / i];
            }
            printf (PLL"
    ", Answer); 
        }
        return 0;
    }
  • 相关阅读:
    Linux目录结构
    Linux简介
    队列、生产者消费者模型
    Process的几个用法和守护进程
    并发编程(初学)
    网络编程知识点小结
    用socketserver模块实现并发
    粘包问题、解决粘包问题和struct模块
    模拟ssh功能和subprocess模块
    socket 套接字编程
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/8066270.html
Copyright © 2011-2022 走看看