BZOJ2301: [HAOI2011]Problem b 莫比乌斯反演

分析:对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。

然后对于求这样单个的gcd(x,y)=k的,我们通常采用莫比乌斯反演

但是,时间复杂度是O(n*(n/k))的,当复杂度很坏的时候,当k=1时,退化到O(n^2),超时

然后进行分块优化,时间复杂度是O(n*sqrt(n))

#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef long long LL;
const int N=5e4+5;
const int INF=0x3f3f3f3f;
bool vis[N];
int prime[N],mu[N],cnt;
void getmu()
{
    mu[1] = 1;
    for(int i=2; i<=N-5; i++)
    {
        if(!vis[i])
        {
            prime[++cnt] = i;
            mu[i] = -1;
        }
        for(int j=1; j<=cnt&&i*prime[j]<=N-5; j++)
        {
            vis[i*prime[j]] = 1;
            if(i%prime[j]) mu[i*prime[j]] = -mu[i];
            else
            {
                mu[i*prime[j]] = 0;
                break;
            }
        }
    }
}
LL solve(int n,int m,int k){
   n/=k,m/=k;
   int l=min(n,m);
   LL ans=0;
   for(int i=1,j;i<=l;i=j+1){
     j=min(n/(n/i),m/(m/i));
     ans+=1ll*(mu[j]-mu[i-1])*(n/i)*(m/i);
   }
   return ans;
}
int main(){
    getmu();
    for(int i=1;i<=N-5;++i)mu[i]+=mu[i-1];
    int T;
    scanf("%d",&T);
    while(T--){
       int a,b,c,d,k;
       scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
       printf("%lld\n",solve(b,d,k)-solve(b,c-1,k)-solve(a-1,d,k)+solve(a-1,c-1,k));
    }
    return 0;
}

时间: 2024-10-03 22:45:24

BZOJ2301: [HAOI2011]Problem b 莫比乌斯反演的相关文章

[BZOJ1101&amp;BZOJ2301][POI2007]Zap [HAOI2011]Problem b|莫比乌斯反演

对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a,y<=b,并且gcd(x,y)=d. 我们可以令F[n]=使得n|(x,y)的数对(x,y)个数 这个很容易得到,只需要让x,y中都有n这个因子就好了,也就是[a/n]*[b/n]个数对(向下取整) 然后设题中所要求的为f[n],很容易得知,F[n]=∑f[d](n|d) 莫比乌斯反演可以得到f[n]=∑μ(d/n)F[d](n|d) 这样是O(n),然而数据范围5*10^4显然不能通过 f[n]=∑μ(d/n)[a/d][b/d]

bzoj 2301: [HAOI2011]Problem b 莫比乌斯反演

2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 3679  Solved: 1648[Submit][Status][Discuss] Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数n,接下来n行每行五个整数,分别表示a.b.c.d.k Outp

【bzoj2301】[HAOI2011]Problem b 莫比乌斯反演

Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数n,接下来n行每行五个整数,分别表示a.b.c.d.k Output 共n行,每行一个整数表示满足要求的数对(x,y)的个数 Sample Input 22 5 1 5 11 5 1 5 2 Sample Output 143 HINT 100%的数据满足:1≤n≤50000,1≤a≤b≤50000

Luogu P2522 [HAOI2011]Problem b 莫比乌斯反演

设$f(d)=\sum_{i=1}^N\sum_{j=1}^M[gcd(i,j)==d],\\F(n)=\sum_{n|d}f(d)=\lfloor \frac{N}{n} \rfloor \lfloor \frac{M}{n} \rfloor$ 则$f(n)$ $=\sum_{n|d}\mu(\frac{n}{d})F(d)$ $=\sum_{n|d}\mu(\frac{n}{d})\lfloor \frac{N}{d} \rfloor \lfloor \frac{M}{d} \rfloor$

bzoj2301 [HAOI2011]Problem b【莫比乌斯反演 分块】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2301 很好的一道题.首先把每个询问转化为4个子询问,最后的结果就是这四个子询问的记过加加减减,类似二维前缀和.那么问题转化为在1 <= x <= lmtx, 1 <= y <= lmty时gcd(x, y) == k的对数,这个问题在转化一下,转化成1 <= x <= lmtx / k,1 <= y <= lmty / k时x与y互质的对数.莫比乌斯反

[HAOI2011][bzoj2301] Problem b [莫比乌斯反演+容斥原理+分块前缀和优化]

题面: 传送门 有洛谷就尽量放洛谷链接呗,界面友好一点 思路: 和HDU1695比较像,但是这一回有50000组数据,直接莫比乌斯反演慢慢加的话会T 先解决一个前置问题:怎么处理a,c不是1的情况? 很简单,容斥原理搞之 我们设f(x,y)代表gcd(i,j)==e(1<=i<=x,1<=j<=y)的无序数对(i,j)的个数 那么本题答案相当于f(d,b)-f(c-1,b)-f(a-1,d)+f(a-1,c-1) 再来看反演超时的问题 我们注意到原反演过程中,f(1)==mu(i)

【BZOJ2301】【HAOI2011】Problem b [莫比乌斯反演]

Problem b Time Limit: 50 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数n,接下来n行每行五个整数,分别表示a.b.c.d.k Output 共n行,每行一个整数表示满足要求的数对(x,y)的个数. Sample Inp

bzoj2301: [HAOI2011]Problem b懵逼乌斯反演

属于结果的和好求但是结果不好求的题 (轻易能得到以k的倍数为最大公约数的对数,但是不好直接求k) 所以一波反演结束 其实反演的时候完全没有反演的感觉,就是不停地恒等变形 算是懵逼乌斯反演最简单的例题 1 #include <bits/stdc++.h> 2 using namespace std; 3 int n,m,a,b,c,d,k,mu[50001],p[50001];bool o[50001]; 4 int calc(int n,int m) 5 { 6 int ret=0;if(n&

BZOJ2301 [HAOI2011]Problem b

什么东西... 搞了半天Mobius反演到底是什么还是没搞定...(至少会求了嘛...好不好) 但是程序写出来了^_^,可惜意义不明T T 1 /************************************************************** 2 Problem: 2301 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:10604 ms 7 Memory:1244 kb 8 *************