• hdu 4746 Mophues


              莫比乌斯反演。先初始化出所有数有多少个质因子和mobius。然后处理mob_sum[ i ][ j ],表示当公因子的因子个数小于等于 j 个的mobius前 i 项和。然后分块求和即可。

             分块处理部分见(不会莫比乌斯反演的同学也可以去这里学一下)http://wenku.baidu.com/view/fbe263d384254b35eefd34eb.html

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define CLR(a, b) memset(a, b, sizeof(a))
    
    using namespace std;
    const int N = 500100;
    
    bool isp[N];
    int p[N], cnt[N], mob[N];
    int mob_sum[N][20];
    
    #define mbs mob_sum
    
    void Mobius()
    {
        CLR(isp, 0);CLR(cnt, 0);
        int tot = 0;mob[1] = 1;
        for(int i = 2; i < N; i ++)
        {
            if(!isp[i])
            {
                p[tot ++] = i;
                mob[i] = -1;cnt[i] = 1;
            }
            for(int j = 0; j < tot && p[j] * i < N; j ++)
            {
                isp[p[j] * i] = true;
                cnt[i * p[j]] = cnt[i] + 1;
                if(i % p[j] == 0)
                {
                    mob[p[j] * i] = 0;
                    break;
                }
                else
                {
                    mob[p[j] * i] = -mob[i];
                }
            }
        }
    }
    
    void init()
    {
        Mobius();CLR(mbs, 0);
        for(int i = 1; i < N; i ++)//求出单项的mbs[i][j],表示的是i为公因子时的情况。
            for(int j = i; j < N; j += i)
            {
                mbs[j][cnt[i]] += mob[j / i];
            }//以下是求前缀和。
        for(int i = 1; i < N; i ++)
            for(int j = 0; j < 19; j ++)
            {
                mbs[i][j] += mbs[i - 1][j];
            }
        for(int i = 0; i < N; i ++)
            for(int j = 1; j < 19; j ++)
            {
                mbs[i][j] += mbs[i][j - 1];
            }
    }
    
    int main()
    {
        //freopen("input.txt", "r", stdin);
        int q, n, m, p;LL ans;
        init();scanf("%d", &q);
        while(q --)
        {
            scanf("%d%d%d", &n, &m, &p);
            if(p >= 19) {printf("%I64d
    ", (LL)n * m); continue;}
            if(n > m) swap(n, m);
            ans = 0;
            for(int i = 1, j = 1; i < n; i = j + 1)
            {
                j = min(n / (n / i), m / (m / i));
                ans += (LL)(mbs[j][p] - mbs[i - 1][p]) * (n / i) * (m / i);
            }
            printf("%I64d
    ", ans);
        }
    }
    


  • 相关阅读:
    Node.js系列基础学习-----回调函数,异步
    Git版本控制工具学习
    大三下学期计划
    JavaScript基础插曲---apply,call和URL编码等方法
    JavaScript基础插曲-练习
    Jira内存调整
    IntelliJ IDEA 简单设置
    介绍一个国内强大的API接口文档写作网站showdoc
    使用IntelliJ IDEA 配置Maven(入门)
    Jira内存调整
  • 原文地址:https://www.cnblogs.com/riskyer/p/3347895.html
Copyright © 2020-2023  润新知