zoukankan      html  css  js  c++  java
  • HDU6715 算术(莫比乌斯反演)

    HDU6715 算术

    莫比乌斯反演的变形。

    (mu(lcm(i,j))) 变换,易得 (mu(lcm(i,j)) = mu(i)cdotmu(j)cdot mu(gcd(i,j))) 。那么有:

    [egin{split} sum_{i=1}^{n} sum_{j=1}^{m} mu(lcm(i,j)) &= sum_{i=1}^{n}mu(i) sum_{j=1}^{m}mu(j)cdot mu(gcd(i,j)) \ &= sum_{d=1}^{min(n,m)}sum_{i=1}^{n/d}sum_{j=1}^{m/d}mu(id)mu(jd)mu(d)[gcd(i,j)=1] end{split}]

    由于莫比乌斯函数的性质 (sum_{d | n}mu(d)=[n=1]) ,我们有:

    [egin{split} ext{上式} = sum_{d=1}^{min(n,m)}sum_{d_1 = 1}^{min(n,m)/d}sum_{i=1}^{n/dd_1}sum_{j=1}^{m/dd_1}mu(idd_1)mu(jdd_1)mu(d)mu(d_1) end{split}]

    我们令 (T = dd_1) ,有:

    [ ext{上式}=sum_{T=1}^{min(n,m)}sum_{d|T}sum_{i=1}^{n/T}sum_{j=1}^{m/T}mu(iT)mu(jT)mu(d)mu(T/d) ]

    (f(T) = sum_{d|T} mu(d)mu(T/d))

    (g(T,N,M)=sum_{i=1}^{N}sum_{j=1}^{M}mu(iT)mu(jT)=(sum_{i=1}^{N}mu(iT))cdot(sum_{j=1}^{M}mu(jT)))

    那么我们有:

    [ ext{上式}=sum_{T=1}^{min(n,m)} f(T)cdot g(T,n/T,m/T) ]

    (g(T,n/T,m/T)) 可以在 (O(n/T+m/T)) 的时间内计算。

    时间复杂度为 (O(nlog n))

    #include<stdio.h>
    #include<algorithm>
    
    using namespace std;
    
    const int maxn = 1000005;
    
    int t, n, m, tot;
    int mu[maxn], check[maxn], prime[maxn];
    long long ans, f[maxn];
    
    void init()
    {
        mu[1] = 1; tot = 0;
        for(int i = 2; i <= 1000000; i++){
            if(check[i] == 0){
                mu[i] = -1;
                prime[++tot] = i;
            }
            for(int j = 1; j <= tot && prime[j] * i <= 1000000; j++){
                check[i * prime[j]] = 1;
                if(i % prime[j] == 0) break;
                mu[i * prime[j]] = -1 * mu[i];
            }
        }
        for(int i = 1; i <= 1000000; i++){
            for(int j = 1; j * i <= 1000000; j++){
                f[i * j] += mu[i] * mu[j];
            }
        }
    }
    int main()
    {
        init();
        for(scanf("%d", &t); t--;){
            scanf("%d%d", &n, &m);
            ans = 0;
            for(int T = 1; T <= min(n, m); T++){
                if(f[T]){
                    long long g1 = 0, g2 = 0;
                    for(int i = 1; i * T <= n; i++) g1 += mu[i * T];
                    for(int i = 1; i * T <= m; i++) g2 += mu[i * T];
                    ans += f[T] * g1 * g2;
                }
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    27. Remove Element
    列表变成字典
    1. Two Sum
    CVPR2019:What and How Well You Performed? A Multitask Learning Approach to Action Quality Assessment
    959. Regions Cut By Slashes
    118. Pascal's Triangle
    loj3117 IOI2017 接线 wiring 题解
    题解 NOI2019 序列
    题解 省选联考2020 组合数问题
    题解 Educational Codeforces Round 90 (Rated for Div. 2) (CF1373)
  • 原文地址:https://www.cnblogs.com/solvit/p/11423625.html
Copyright © 2011-2022 走看看