HDU 4746 Mophues【莫比乌斯反演】

原创 2016年05月30日 21:42:16

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4746

题意:

1x,yn , 求gcd(x,y)分解后质因数个数小于等k(x,y)的对数。

分析:

莫比乌斯反演。
还是一个套路,我们设
f(d):满足gcd(x,y)=dx,y均在给定范围内的(x,y)的对数。
F(d):满足d|gcd(x,y)x,y均在给定范围内的(x,y)的对数。
显然F(x)=[n/x][m/x],反演后我们得到

f(x)=x|dμ(d/x)[n/d][m/d]

最直接的方法,枚举质数p,那么
ans=pmin(n,m)(dmin(n/p,m/p)μ(d)[n/(pd)][m/(pd)])

这样肯定会超时。
我们令a=pd,那么
ans=a=1min(n,m)[n/a][m/a]p|aμ(a/p)

我们希望快速获得每个a对应的p|aμ(a/p),由于题目规定了最大的质因子数目,所以我们增加一维,设f[i][j]表示质因子数目小于等于j时 前i项和,根据公式计算即可。
最后我们再取个前缀和就好了。注意这里仍然使用了分段优化。

代码:

/*
-- Hdu 4746
-- Created by jiangyuzhu
-- 2016/5/30
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <stack>
using namespace std;
typedef long long ll;
#define sa(n) scanf("%d", &(n))
#define sal(n) scanf("%I64d", &(n))
#define pl(x) cout << #x << " " << x << endl
#define mdzz cout<<"mdzz"<<endl;
const int maxn = 5e5 + 5 ;
int tot = 0;
int miu[maxn], prime[maxn], f[maxn][20 + 5];
int cnt[maxn];
bool flag[maxn];
void mobius()
{
    miu[1] = 1;
    tot = 0;
    for(int i = 2; i < maxn; i++){
        if(!flag[i]){
            prime[tot++] = i;
            miu[i] = -1;
            cnt[i] = 1;
        }
        for(int j = 0; j < tot && i * prime[j] < maxn; j++){
            flag[i * prime[j]] = true;
            cnt[i * prime[j]] = cnt[i] + 1;
            if(i % prime[j]){
                miu[i * prime[j]] = -miu[i];
            }
            else{
                miu[i * prime[j]] = 0;
                break;
            }
        }
    }
    for(int i = 1; i < maxn; i++){
        for(int j = i; j < maxn; j += i){
            f[j][cnt[i]] += miu[j / i];
        }
    }
    for(int i = 1; i < maxn; i++){
        for(int j = 1; j < 20; j++){
            f[i][j] +=  f[i][j - 1] ;
        }
    }
    //前缀和
    for(int i = 1; i < maxn; i++){
        for(int j = 0; j < 20; j++){
            f[i][j] += f[i - 1][j];
        }
    }
}
int main (void)
{
    mobius();
    int T;sa(T);
    int n, m, k;
    for(int kas = 1; kas <= T; kas++){
       scanf("%d%d%d", &n, &m, &k);
       ll ans = 0;
       k = min(k, 19);
       int j;
       if(n > m) swap(n, m);
       for(int i = 1; i <= n; i = j + 1){
           j = min(n /(n / i), m / (m / i ));
          ans += (n / j) * 1ll * (m / j) * (f[j][k] - f[i - 1][k]);
       }
       printf("%lld\n", ans);
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 4746 Mophues (莫比乌斯反演应用)

HDU 4746 Mophues (莫比乌斯反演应用)

HDU 4746 Mophues(莫比乌斯反演)

题意:给出n, m, p,求有多少对a, b满足gcd(a, b)的素因子个数 思路:不难看出可以看出p最多不超过19. 首先考虑这个问题的简化版,求gcd(a,b)小于等于d的数对的数量。 对...

HDU 4746 Mophues 莫比乌斯第三弹

题意:1 例:24=2*2*2*3,k=4 解:设f[n]为gcd(a,b)=n的对数       F[d]为d|gcd(a,b)的对数     f[n]=sigema(mu[i],F[i*n...
  • trq1995
  • trq1995
  • 2015年08月02日 16:35
  • 388

HDU4746 Mophues(莫比乌斯反演)

Mophues Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327670/327670 K (Java/Others) Total ...
  • mowayao
  • mowayao
  • 2014年08月27日 19:48
  • 654

HDU 4746 Mophues(有趣的前缀和/莫比乌斯反演)

题目链接: HDU 4746 Mophues 题意: 令gcd(a,b)=d,对d质因子分解得到质因子个数为k如果k≤C,则称k为C的lucky数字,给出n,m,p,求a∈[1,n],b∈[1,...
  • Ramay7
  • Ramay7
  • 2016年06月05日 21:56
  • 314

HDU 4746 Mophues(莫比乌斯反演)

这道题是跟着秦总博客学的:附上链接:秦总博客用f(d)f(d)表示满足d=gcd(x,y)d=gcd(x,y)且1...

hdu 4746 Mophues 莫比乌斯反演

Mophues Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327670/327670 K (Java/Others) Total ...

hdu_4746_莫比乌斯反演

下面这个题解很详细。。 http://blog.csdn.net/acdreamers/article/details/12871643

hdu4746(莫比乌斯反演)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4746   题意:给出n, m, p,求有多少对a, b满足gcd(a, b)的素因子个数 分析:...

hdu 4746 Mophues 莫比乌斯 分块优化

DescriptionAs we know, any positive integer C ( C >= 2 ) can be written as the multiply of some prim...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDU 4746 Mophues【莫比乌斯反演】
举报原因:
原因补充:

(最多只允许输入30个字)