zoukankan      html  css  js  c++  java
  • P3327 [SDOI2015]约数个数和

    (color{#0066ff}{ 题目描述 })

    (d(x))(x)的约数个数,给定(N、M),求 (sum^N_{i=1}sum^M_{j=1}d(ij))

    (color{#0066ff}{输入格式})

    输入文件包含多组测试数据。第一行,一个整数T,表示测试数据的组数。接下来的T行,每行两个整数N、M。

    (color{#0066ff}{输出格式})

    T行,每行一个整数,表示你所求的答案。

    (color{#0066ff}{输入样例})

    2
    7 4
    5 6
    

    (color{#0066ff}{输出样例})

    110
    121
    

    (color{#0066ff}{数据范围与提示})

    1<=N, M<=50000

    1<=T<=50000

    (color{#0066ff}{ 题解 })

    题目要求

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

    看似不好求,然而有结论。。。

    [sum_{i=1}^nsum_{j=1}^msum_{x|i}sum_{y|j} [gcd(x, y)==1] ]

    然后就是套路了

    [sum_{i=1}^nsum_{j=1}^msum_{x|i}sum_{y|j} sum_{d|gcd(x, y)} mu(d) ]

    枚举x和y,注意还要是i和j的约数

    [sum_{d = 1}^{min(n,m)}sum_{i=1}^nsum_{j=1}^msum_{x=1}^{lfloorfrac i d floor}sum_{y=1}^{lfloorfrac j d floor}[xd|i&&yd|j] mu(d) ]

    能提前的全部提前

    [sum_{d = 1}^{min(n,m)}mu(d)sum_{i=1}^nsum_{j=1}^msum_{x=1}^{lfloorfrac i d floor}sum_{y=1}^{lfloorfrac j d floor}[xd|i&&yd|j] ]

    [sum_{d = 1}^{min(n,m)}mu(d)sum_{i=1}^nsum_{x=1}^{lfloorfrac i d floor}[xd|i]sum_{j=1}^msum_{y=1}^{lfloorfrac j d floor}[yd|j] ]

    最后就成这东西了

    [sum_{d = 1}^{min(n,m)}mu(d)sum_{x=1}^{lfloorfrac n d floor}lfloorfrac{n}{xd} floorsum_{y=1}^{lfloorfrac m d floor}lfloorfrac{m}{yd} floor ]

    (lfloorfrac{n}{d} floor)当成一个整体,那么其实就是(egin{aligned}sum_{x=1}^n lfloorfrac{n}{x} floorend{aligned})

    直接数列分块即可

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
        char ch; LL x = 0, f = 1;
        while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
        for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
        return x * f;
    }
    const int maxn = 5e4 + 100;
    LL pri[maxn], mu[maxn], cnt[maxn], ans[maxn], tot;
    bool vis[maxn];
    void predoit() {
        mu[1] = 1;
        for(int i = 2; i < maxn; i++) {
            if(!vis[i]) pri[++tot] = i, mu[i] = -1;
            for(int j = 1; j <= tot && (LL)i * pri[j] < maxn; j++) {
                vis[i * pri[j]] = true;
                if(i % pri[j] == 0) break;
                else mu[i * pri[j]] = -mu[i];
            } 
        }
        for(int i = 1; i < maxn; i++) {
            mu[i] += mu[i - 1];
            for(LL l = 1, r; l <= i; l = r + 1) {
                r = i / (i / l);
                ans[i] += (r - l + 1) * (i / l);
            }
        }
    }
    LL work(LL n, LL m) {
        LL res = 0;
        for(LL l = 1, r; l <= std::min(n, m); l = r + 1) {
            r = std::min(n / (n / l), m / (m / l));
            res += (mu[r] - mu[l - 1]) * ans[n / l] * ans[m / l];
        }
        return res;
    }
    int main() {
        predoit();
        for(int T = in(); T --> 0;) printf("%lld
    ", work(in(), in()));
        return 0;
    }
    
  • 相关阅读:
    C++实现数字媒体三维图像渲染
    C++实现数字媒体三维图像变换
    C++实现数字媒体二维图像变换
    C++实现glut绘制点、直线、多边形、圆
    语音识别之梅尔频谱倒数MFCC(Mel Frequency Cepstrum Coefficient)
    Java中的BigDecimal类精度问题
    spring 手册
    bootstrap 参考文档
    springBoot入门文章
    JNDI
  • 原文地址:https://www.cnblogs.com/olinr/p/10327728.html
Copyright © 2011-2022 走看看