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;
    }
    
  • 相关阅读:
    8.JavaCC官方入门指南-例3
    7.JavaCC官方入门指南-例2
    6.JavaCC官方入门指南-例1
    5.JavaCC官方入门指南-概述
    4.JavaCC处理中文字符
    3.JavaCC 语法描述文件的格式解析
    2.idea安装JavaCC插件.md
    SQL 高效运行注意事项(二)
    视图用到的表更新表结构时注意刷新视图
    SQL 高效运行注意事项(一)
  • 原文地址:https://www.cnblogs.com/solvit/p/11423625.html
Copyright © 2011-2022 走看看