hdu4746莫比乌斯反演进阶题

Mophues

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327670/327670 K (Java/Others)
Total Submission(s): 1922    Accepted Submission(s): 791

Problem Description

As we know, any positive integer C ( C >= 2 ) can be written as the multiply of some prime numbers:
    C = p1×p2× p3× ... × pk
which p1, p2 ... pk are all prime numbers.For example, if C = 24, then:
    24 = 2 × 2 × 2 × 3
    here, p1 = p2 = p3 = 2, p4 = 3, k = 4

Given two integers P and C. if k<=P( k is the number of C‘s prime factors), we call C a lucky number of P.

Now, XXX needs to count the number of pairs (a, b), which 1<=a<=n , 1<=b<=m, and gcd(a,b) is a lucky number of a given P ( "gcd" means "greatest common divisor").

Please note that we define 1 as lucky number of any non-negative integers because 1 has no prime factor.

Input

The first line of input is an integer Q meaning that there are Q test cases.
Then Q lines follow, each line is a test case and each test case contains three non-negative numbers: n, m and P (n, m, P <= 5×105. Q <=5000).

Output

For each test case, print the number of pairs (a, b), which 1<=a<=n , 1<=b<=m, and gcd(a,b) is a lucky number of P.

Sample Input

2

10 10 0

10 10 1

Sample Output

63

93

http://blog.csdn.net/wh2124335/article/details/11846661 转载自此

记录一下自己的思路

未简化过的代码核心应该是这样的

   for(int i=1;i<=n;++i)//枚举每个因子
   if(d[i]<=k)//如果因子的素数质因子小于等于k
    for(int j=i;j<=n;j+=i) ans+=u(j/i)*(n/i)*(m/i)//枚举F(i);

利用的是第二个,然后可以发现,对于每个数字i,他的倍数j的系数都要加上u[j/i],可以与处理出来U(N),其中U(i)就是u[i/第一个因子]+u[i/第二个因子]+....(这里的U先不考虑素因子个数限制)

那么上述式子就可以化简成为

for(int i=1;i<=n;++i) ans+=U(i)*(n/i)*(m/i);//直接枚举

然后U(i)考虑素因子个数限制的话,那么显然预处理也是可以搞出来的,详细见代码,代码里的cnt[N][19]就是U考虑限制的。

然后就是普通的分块操作,为了简化时间,因为W=(n/i)*(m/i),i倘若在一定范围内,这个W是不变的,所以可以加速。

所以最后就是这样了

for(int i=1,last=i;i<=n;i=last+1){
            last=min(n/(n/i),m/(m/i));
            ans+=(ll)(cnt[last][k]-cnt[i-1][k])*(n/i)*(m/i);
        }
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;
const int maxn = 500100;
typedef long long ll;
int mu[maxn],sum[maxn],num[maxn];
ll cnt[maxn][19];
bool flag[maxn];
vector<int>prime;
void init(){
    mu[1]=1;
    for(int i=2;i<maxn;i++){
        if(!flag[i]){
            prime.push_back(i);
            mu[i]=-1;
            num[i]=1;
        }
        for(int j=0;j<prime.size()&&i*prime[j]<maxn;j++){
            flag[i*prime[j]]=true;
            num[i*prime[j]]=num[i]+1;
            if(i%prime[j])mu[i*prime[j]]=-mu[i];
            else {mu[i*prime[j]]=0;break;}
        }
    }
    for(int i=1;i<maxn;i++){
        for(int j=i;j<maxn;j+=i){
            cnt[j][num[i]]+=mu[j/i];
        }
    }
    for(int i=0;i<maxn;i++){
        for(int j=1;j<19;j++){
            cnt[i][j]+=cnt[i][j-1];
        }
    }
    for(int i=1;i<maxn;i++){
        for(int j=0;j<19;j++){
            cnt[i][j]+=cnt[i-1][j];
        }
    }
}
int main(){
    init();
    int q;
    scanf("%d",&q);
    while(q--){
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        k=min(k,18);
        ll ans=0;
        if(n>m)swap(n,m);
        for(int i=1,last=i;i<=n;i=last+1){
            last=min(n/(n/i),m/(m/i));
            ans+=(ll)(cnt[last][k]-cnt[i-1][k])*(n/i)*(m/i);
        }
        //printf("%lld\n",ans);
        printf("%I64d\n",ans);
    }
}
时间: 2024-10-20 06:21:06

hdu4746莫比乌斯反演进阶题的相关文章

莫比乌斯反演简单题

莫比乌斯函数 这里简述一下莫比乌斯函数: 若d=1 那么μ(d)=1 若d=p1p2-pr (r个不同质数,且次数都为一)μ(d)=(-1)^r 其余 μ(d)=0 GCD 题目传送:HDU - 1695 - GCD 题意:求[1,n],[1,m]中gcd为k的两个数的对数 思路:这里可以转化一下,也就是[1,n/k],[1,m/k]之间互质的数的个数,模板题 AC代码: #include <map> #include <set> #include <list> #in

hdu 1695 莫比乌斯反演

hdu 1695 莫比乌斯反演 题意: 给出a,b,c,d,k, 求满足a <= x <= b && c <= y <= d && gcd(x,y)=k 的数对(x,y)的对数. 限制: a=c=1; 0 < b,c <= 1e5; (n1,n2) 和 (n2,n1) 算为同种情况 思路: 其实是求满足1 <= x <= b/k && 1 <= y <= d/k && gcd(x,y

HDU 4746 (莫比乌斯反演) Mophues

这道题看巨巨的题解看了好久,好久.. 本文转自hdu4746(莫比乌斯反演) 题意:给出n, m, p,求有多少对a, b满足gcd(a, b)的素因子个数<=p,(其中1<=a<=n, 1<=b<=m) 分析:设A(d):gcd(a, b)=d的有多少种      设B(j): gcd(a, b)是j的倍数的有多少种,易知B(j) = (n/j)*(m/j)      则由容斥原理得:(注:不同行的μ是不相同的,μ为莫比乌斯函数)      A(1) = μ(1)*B(1)

hdu1569 莫比乌斯反演

hdu 1695 莫比乌斯反演 给出a,b,c,d,k, 求满足a <= x <= b && c <= y <= d && gcd(x,y)=k 的数对(x,y)的对数. a=c=1; 0 < b,c <= 1e5; (n1,n2) 和 (n2,n1) 算为同种情况 其实是求满足1 <= x <= b/k && 1 <= y <= d/k && gcd(x,y)=1 的 数对(x,y

【HDU1695】GCD(莫比乌斯反演)

[HDU1695]GCD(莫比乌斯反演) 题面 题目大意 求\(a<=x<=b,c<=y<=d\) 且\(gcd(x,y)=k\)的无序数对的个数 其中,你可以假定\(a=c=1\) 所有数都\(<=100000\) 数据组数\(<=3000\) 题解 莫比乌斯反演 作为一道莫比乌斯反演的题目 首先我们要迈出第一步 如果有\(gcd(x,y)=k\) 那么,我们就有\(gcd(\frac{x}{k},\frac{y}{k})=1\) 所以,现在问题相当于转化为了求 \(

【BZOJ4407】于神之怒加强版(莫比乌斯反演)

[BZOJ4407]于神之怒加强版(莫比乌斯反演) 题面 BZOJ 求: \[\sum_{i=1}^n\sum_{j=1}^mgcd(i,j)^k\] 题解 根据惯用套路 把公约数提出来 \[\sum_{d=1}^nd^k\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==d]\] 再提一次 \[\sum_{d=1}^nd^k\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}[gcd(i,j)==1]\] 后面这个东西很显然可以数论分块+莫比乌斯反演做到\(O(\

莫比乌斯反演题目列表

前言: 本题表中,凡是涉及\(n.m\),都默认\(n \leq m\). Part1 这些题目都非常水,莫比乌斯反演入门题, 主要是对莫比乌斯反演应用有一个基本概念. 1.[HAOI2011]Problem b (具体题目戳我) 题目:一组数据(\(a.d.c.d \leq 5×10^4\))求 \[\sum_{i=a}^{b} \sum_{j=c}^d [gcd(i,j)=d]\] 题解: \[\sum_{i=1}^{n} \sum_{j=1}^m [gcd(i,j)=d] = \sum_{

【UVa11426】GCD - Extreme (II)(莫比乌斯反演)

[UVa11426]GCD - Extreme (II)(莫比乌斯反演) 题面 Vjudge 题解 这.. 直接套路的莫比乌斯反演 我连式子都不想写了 默认推到这里把.. 然后把\(ans\)写一下 \[ans=\sum_{d=1}^nd\sum_{i=1}^{n/d}\mu(i)[\frac{n}{id}]^2\] 令\(T=id\) 然后把\(T\)提出来 \[ans=\sum_{T=1}^n[\frac{n}{T}]^2\sum_{d|T}d\mu(\frac{T}{d})\] 后面那一堆

【BZOJ2820】YY的GCD(莫比乌斯反演)

[BZOJ2820]YY的GCD(莫比乌斯反演) 题面 讨厌权限题!!!提供洛谷题面 题解 单次询问\(O(n)\)是做过的一模一样的题目 但是现在很显然不行了, 于是继续推 \[ans=\sum_{d=1}^n[d\_is\_prime]\sum_{i=1}^{n/d}[\frac{n}{id}][\frac{m}{id}]\] 老套路了 令\(T=id\) \[ans=\sum_{T=1}^{n}[\frac{n}{T}][\frac{m}{T}]\sum_{d|T}[d\_is\_prim