欧拉函数&莫比乌斯反演

本文汇集了几道涉及欧拉函数和莫比乌斯反演的题目,介绍了如何利用这两个概念解决实际问题。通过讨论[BZOJ 2301]、[BZOJ 2440]等题目的解法,阐述了在求解gcd相关问题时,如何运用莫比乌斯函数进行二分和容斥原理的结合,以及在求解方案数问题时,如何计算约数个数并利用欧拉函数优化算法。文章还提及了数据结构如树状数组在优化算法效率方面的作用。
摘要由CSDN通过智能技术生成

近几天做了几道有关反演的问题,在此集合一下吧。

1、[BZOJ 2301]HAOI2011 Problem b

2、[BZOJ 2440]中山市选2011 完全平方数

3、gcd

4、[BZOJ 2186]SDOI2008 莎拉公主的困惑

5、[BZOJ 3529]SDOI2014 数表


(蒟蒻自认为反演一类的的题目重要的就是记住两个重要的公式:1、sigma(mu[i] , i|n ) = [n==1]   2、sigma(phi[i] , i|n ) = n


题解:

1、[BZOJ 2301]HAOI2011 Problem b

这基本上算是入门题了吧。。。。

gcd(a,b)==k等价于gcd(a/k,b/k)==1,这样我们将范围除k,等价到求区间内互质的二元组数。

假设query(n,m)得到gcd(a,b)==1的数量,那么答案很明显就是gcd(b,d) - gcd(a-1,d) - gcd(b,c-1) + gcd(a-1,c-1)

简单了,下面简述一下推导过程吧


为了不被多组数据卡掉,我们观察到n/k的答案只有不超过根号n个不同答案,对mu[]前缀和优化,那么每次询问时O(sqrt(n))的复杂度

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
 
using namespace std;
int l,r,ans,mid,INF,K,Case,tot;
int prime[41005],mu[41005],i,j;
bool check[41005];
 
void init(){
  mu[1]=1;
  for (i=2;i<41000;i++){
    if (!check[i]) mu[i]=-1, prime[++tot]=i;
    for (j=1;j<=tot;j++){
      if (i*prime[j]>41000) break;
      check[i*prime[j]]=1;
      if (i%prime[j]==0) {mu[i*prime[j]]=0;break;}
        else mu[i*prime[j]] = -mu[i];
    }
  }
}
 
bool Judge(){
  int ret=0;
  for (int i=1;i*i<=mid;i++)
    ret+=(mid/i/i)*mu[i];
  return (ret>=K);
}
 
int main(){
  //freopen("2440.in","r",stdin);
  //freopen("2440.out","w",stdout);
  init();
  INF=41000; INF=INF*INF;
  scanf("%d",&Case);
  while (Case--){
    scanf("%d",&K);
    l=1; r=INF;
    while (l<=r){
      mid=((long long)l+r)>>1;
      if (Judge()) ans=mid, r=mid-1;
        else l=mid+1;
    }
    printf("%d\n",ans);
  }
  return 0;
}

2、[BZOJ 2440]中山市选2011
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值