zoukankan      html  css  js  c++  java
  • hdu4746 Mophues 莫比乌斯

    /**
    题目:hdu4746 Mophues
    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4746
    题意:求x,y在给定范围内gcd(x,y)分解素因子的个数<=p的对数。
     (n, m, P <= 5×105. Q <=5000).
    思路:
    
    f(n)表示给定范围内gcd(x,y)==n的对数。
    g(n)表示给定范围内gcd(x,y)为n的倍数的对数。
    
    f(n) = sigma[n|d]mu[d/n]*g(d) = sigma[n|d]mu[d/n]*(n/d)*(m/d) ;
    
    ans = sigma[1<=x<=min(n,m)]sigma[x|d]mu[d/x]*g(d)
    
        = sigma[1<=d<=min(n,m)](g(d)*sigma[x是d的约数]mu[d/x]);
    
        sigma[x是d的约数]mu[d/x] 是 g(d)的系数。系数可以用前缀和预处理。
    
        但是本题要求的是gcd(x,y)的分解质因子个数<=p; 所以sigma[x是d的约数]mu[d/x]这里x不仅是d的约数,且要满足x的分解质因子个数<=p (ps:这里的x就是f(n)的n);
    
        定义sum[d]表示 sigma[x是d的约数]mu[d/x], 那么sum[d][num]表示 sigma[x是d的约数,x的分解质因子个数为num]mu[d/x];
    
        然后处理sum[d][num]表示sum[d][0]~sum[d][num]的前缀和。
    
        然后处理sum[d][num]表示sum[0][num]~sum[d][num]的前缀和。
    
        那么就可以用除法的取值sqrt(N)级别快速计算。
    
    
    
    
    */
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <iostream>
    #include <vector>
    #include <map>
    using namespace std;
    typedef long long LL;
    #define ms(x,y) memset(x,y,sizeof x)
    typedef pair<int, int> P;
    const LL INF = 1e10;
    const int mod = 1e9 + 7;
    const int maxn = 5e5 + 100;
    int prime[maxn], tot, not_prime[maxn];
    int mu[maxn], sum[maxn][20], cnt[maxn];
    void mobius()
    {
        mu[1] = 1;
        tot = 0;
        for(int i = 2; i < maxn; i++){
            if(!not_prime[i]){
                mu[i] = -1;
                prime[++tot] = i;
                cnt[i] = 1;
            }
            for(int j = 1; prime[j]*i<maxn; j++){
                not_prime[prime[j]*i] = 1;
                cnt[prime[j]*i] = cnt[i]+1;///cnt[i]表示i这个数分解素因子的个数。
                if(i%prime[j]==0){
                    mu[prime[j]*i] = 0;
                    break;
                }
                mu[prime[j]*i] = -mu[i];
            }
        }
    
        for(int i = 1; i < maxn; i++){
            for(int j = i; j < maxn; j+=i){
                sum[j][cnt[i]] += mu[j/i];
            }
        }
    
        for(int i = 1; i < maxn; i++){
            for(int j = 1; j < 20; j++){
                sum[i][j] += sum[i][j-1];
            }
        }
    
        for(int j = 0; j < 20; j++){
            for(int i = 1; i< maxn; i++){
                sum[i][j]  += sum[i-1][j];
            }
        }
    
    }
    LL solve(int n,int m,int p)
    {
        if(n>m) swap(n,m);
        LL ans = 0;
        int last;
        for(int i = 1; i <= n; i = last+1){
            last = min(n/(n/i),m/(m/i));
            ans += (LL)(sum[last][p]-sum[i-1][p])*(n/i)*(m/i);
        }
        return ans;
    }
    int main()
    {
        //freopen("YYnoGCD.in","r",stdin);
        //freopen("YYnoGCD.out","w",stdout);
        //freopen("in.txt","r",stdin);
        int n, m, p;
        int T;
        mobius();
        cin>>T;
        while(T--){
            scanf("%d%d%d",&n,&m,&p);
            if(p>19){
                printf("%lld
    ",(LL)n*m); continue;
            }
            printf("%lld
    ",solve(n,m,p));
        }
        return 0;
    }
  • 相关阅读:
    MySQL根据出生日期计算年龄的五种方法比较
    用于测试API并生文档的开发人员工具
    【实例】使用Eolinker工具进行接口测试时传递集合参数的方法
    如何克服API测试中的挑战
    关于API网关(一)性能
    为什么需要监控API
    比Swagger2更好用的自动生成文档工具?对比流程说话!
    如何通过3个步骤执行基本的API测试
    【学习】API接口测试用例编写规则
    微信小程序之蓝牙 BLE 踩坑记录
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7375644.html
Copyright © 2011-2022 走看看