上次看莫比乌斯繁衍反演是一个月前,讲道理没怎么看懂..

然后出去跪了二十天, 然后今天又开始看发现其实并不难理解
 
开个这个仅记录一下写过的题。
HAOI 2011 B
 
这应该是莫比乌斯反演的模板题,有很多题解,不多说。
CODE:
//HAOI 2011 B
//by Cydiater
//2016.7.25
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <iomanip>
#include <string>
#include <queue>
#include <map>
using namespace std;
#define ll long long
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define down(i,j,n)     for(int i=j;i>=n;i--)
#define FILE "b"
;
const int oo=0x3f3f3f3f;
inline int read(){
      ,f=;
      ;ch=getchar();}
      +ch-';ch=getchar();}
      return x*f;
}
,T,a,b,c,d,sum[MAXN],k;
bool vis[MAXN];
namespace solution{
      void make_mu(){
            mu[]=;
            memset(vis,,sizeof(vis));
            up(i,,){
                  ;}
                  ;prime[j]*i<=&&j<=cnt;j++){
                        vis[prime[j]*i]=;
                        )mu[i*prime[j]]=-mu[i];
                        else{
                              mu[i*prime[j]]=;
                              break;
                        }
                  }
            }
            up(i,,)sum[i]=sum[i-]+mu[i];
      }
      int get(int n,int m){
            if(n>m)swap(n,m);
            ;
            ;i<=n;i=pos+){
                  pos=min(n/(n/i),m/(m/i));
                  ans+=(sum[pos]-sum[i-])*(n/i)*(m/i);
            }
            return ans;
      }
}
int main(){
      //freopen("input.in","r",stdin);
      freopen(FILE".in","r",stdin);
      freopen(FILE".out","w",stdout);
      T=read();
      using namespace solution;
      memset(sum,,sizeof(sum));
      make_mu();
      while(T--){
            a=read();b=read();c=read();d=read();k=read();
            a--;c--;
            a/=k;b/=k;c/=k;d/=k;
            printf("%d\n",get(b,d)-get(a,d)-get(b,c)+get(a,c));
      }
      ;
}

BZOJ 1101

上一道题的弱化版..
//BZOJ 1101
//by Cydiater
//2016.7.25
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <map>
#include <iomanip>
using namespace std;
#define ll long long
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define down(i,j,n)     for(int i=j;i>=n;i--)
;
const int oo=0x3f3f3f3f;
inline int read(){
      ,f=;
      ;ch=getchar();}
      +ch-';ch=getchar();}
      return x*f;
}
,sum[MAXN],T;
bool vis[MAXN];
namespace solution{
      void make_mu(){
            memset(mu,,sizeof(mu));
            memset(sum,,sizeof(sum));
            mu[]=;
            up(i,,){
                  ;}
                  ;j<=cnt&&i*prime[j]<=;j++){
                        vis[i*prime[j]]=;
                        )mu[i*prime[j]]=-mu[i];
                        else{
                              mu[i*prime[j]]=;
                              break;
                        }
                  }
            }
            up(i,,)sum[i]=sum[i-]+mu[i];
      }
      int get(int n,int m){
            ;
            if(n>m)swap(n,m);
            ;i<=n;i=pos+){
                  pos=min(m/(m/i),n/(n/i));
                  ans+=(sum[pos]-sum[i-])*(m/i)*(n/i);
            }
            return ans;
      }
}
int main(){
      //freopen("input.in","r",stdin);
      using namespace solution;
      make_mu();
      T=read();
      while(T--){
            int a=read(),b=read(),k=read();
            a/=k;b/=k;
            printf("%d\n",get(a,b));
      }
      ;
}
Vijos 1889
 
题意就是让你求出第N个mu[i]!=0的数。
然后我们知道小于 i的莫比乌斯函数值不为0的数有Σmu[i]*(x/i^2)个(我从黄学长博客上看到的QAQ)
然后我们就可以愉快的二分了
 
PS注意枚举i时要设为ll
//Vijos 1889
//by Cydiater
//2016.7.25
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstring>
#include <string>
#include <ctime>
#include <cmath>
#include <queue>
#include <map>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define ll long long
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define down(i,j,n)     for(int i=j;i>=n;i--)
+;
const int oo=0x3f3f3f3f;
inline ll read(){
      ,f=;
      ;ch=getchar();}
      +ch-';ch=getchar();}
      return x*f;
}
ll N,prime[MAXN],cnt=,mu[MAXN],leftt,rightt,mid;
bool vis[MAXN];
namespace solution{
      void make_mu(){
            memset(vis,,sizeof(vis));
            memset(mu,,sizeof(mu));
            up(i,,){
                  ;}
                  ;prime[j]*i<=&&j<=cnt;j++){
                        vis[prime[j]*i]=;
                        )mu[i*prime[j]]=-mu[i];
                        else{
                              mu[i*prime[j]]=;
                              break;
                        }
                  }
            }
      }
      void init(){
            N=read();
      }
      bool check(ll num){
            ll lim=1LL*sqrt(;
            ;i<=lim;i++)
            ans+=num/(i*i)*mu[i];
            return ans>=N;
      }
      void slove(){
            leftt=N;rightt=25505460948LL;
            <rightt){
                  mid=(leftt+rightt)>>;
                  if(check(mid))    rightt=mid;
                  else              leftt=mid;
            }
            if(check(leftt))cout<<leftt<<endl;
            else            cout<<rightt<<endl;
      }
}
int main(){
      //freopen("input.in","r",stdin);
      //freopen("out.out","w",stdout);
      using namespace solution;
      make_mu();
      init();
      slove();
      ;
}

BZOJ 2440

上面那道题做一下小修改就好了
//bzoj2440
//by Cydiater
//2016.7.25
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstring>
#include <string>
#include <ctime>
#include <cmath>
#include <queue>
#include <map>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define ll long long
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define down(i,j,n)     for(int i=j;i>=n;i--)
+;
const int oo=0x3f3f3f3f;
inline ll read(){
      ,f=;
      ;ch=getchar();}
      +ch-';ch=getchar();}
      return x*f;
}
ll N,prime[MAXN],cnt=,mu[MAXN],leftt,rightt,mid,T;
bool vis[MAXN];
namespace solution{
      void make_mu(){
            memset(vis,,sizeof(vis));
            memset(mu,,sizeof(mu));
            up(i,,){
                  ;}
                  ;prime[j]*i<=&&j<=cnt;j++){
                        vis[prime[j]*i]=;
                        )mu[i*prime[j]]=-mu[i];
                        else{
                              mu[i*prime[j]]=;
                              break;
                        }
                  }
            }
      }
      void init(){
            N=read();
      }
      bool check(ll num){
            ll lim=1LL*sqrt(;
            ;i<=lim;i++)
            ans+=num/(i*i)*mu[i];
            return num-ans>=N;
      }
      void slove(){
            leftt=N;rightt=25505460948LL;
            <rightt){
                  mid=(leftt+rightt)>>;
                  if(check(mid))    rightt=mid;
                  else              leftt=mid;
            }
            if(check(leftt))cout<<leftt<<endl;
            else            cout<<rightt<<endl;
      }
}
int main(){
      //freopen("input.in","r",stdin);
      //freopen("out.out","w",stdout);
      using namespace solution;
      make_mu();
      T=read();
      while(T--){
            init();
            slove();
      }
      ;
}

YY的GCD

要克服公式恐惧症啊= =
 
和B那道题很像,但是与那道题不同的是这道题要求求出所有的素数。
设f(p)为在x在1-n中,y在1-m中满足gcd(x,y)==p的个数
所以我们就可以推出这样一个式子:
 
然后我们就有了暴力求出这个题答案的方法了。
但是显然会超时,考虑优化
 

这样的话如果我们能预处理出,就能很快的求出答案了。显然暴力的方法能预处理出来。

//YY de GCD
//by Cydiater
//2016.7.26
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <cstdlib>
#include <cstdio>
#include <iomanip>
#include <ctime>
using namespace std;
#define ll long long
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define down(i,j,n)     for(int i=j;i>=n;i--)
#define FILE "YYnoGCD"
const int oo=0x3f3f3f3f;
;
inline ll read(){
      ,f=;
      ;ch=getchar();}
      +ch-';ch=getchar();}
      return x*f;
}
,f[MAXN],T,mu[MAXN];
bool vis[MAXN];
namespace solution{
      void make_mu(){
            memset(vis,,sizeof(vis));
            memset(f,,sizeof(f));
            mu[]=;
            up(i,,){
                  ;}
                  up(j,,cnt){
                        )break;
                        vis[prime[j]*i]=;
                        )mu[i*prime[j]]=-mu[i];
                        else{
                              mu[i*prime[j]]=;
                              break;
                        }
                  }
            }
            up(i,,cnt)up(j,,){
                  )break;
                  f[prime[i]*j]+=mu[j];
            }
            up(i,,)f[i]+=f[i-];
      }
      void slove(ll a,ll b){
            ll ans=,pos;
            if(a>b)swap(a,b);
            up(i,,a){
                  pos=min(a/(a/i),b/(b/i));
                  ans+=(f[pos]-f[i-])*(a/i)*(b/i);
                  i=pos;
            }
            cout<<ans<<endl;
      }
}
int main(){
      //freopen("input.in","r",stdin);
      freopen(FILE".in","r",stdin);
      freopen(FILE".out","w",stdout);
      using namespace solution;
      make_mu();
      T=read();
      while(T--){
            ll a=read(),b=read();
            slove(a,b);
      }
      ;
}

BZOJ 4407于神之怒

 
这些题为什么越来越难了QAQ
给下N,M,K.求
下面给出公式的推导:
//BZOJ 4407
//by Cydiater
//2016.7.27
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <queue>
#include <map>
#include <iomanip>
#include <cmath>
#include <ctime>
using namespace std;
#define ll long long
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define down(i,j,n)     for(int i=j;i>=n;i--)
;
const int LIM=5e6;
const int oo=0x3f3f3f3f;
;
inline int read(){
      ,f=;
      ;ch=getchar();}
      +ch-';ch=getchar();}
      return x*f;
}
ll f[MAXN],prime[MAXN],cnt=,N,K,g[MAXN],T;
bool vis[MAXN];
namespace solution{
      inline ll quick_pow(ll a,ll b){
            ll tmp=;
            while(b){
                  )tmp=(tmp*a)%mod;
                  a=(a*a)%mod;
                  b>>=;
            }
            return tmp;
      }
      void pret(){
            memset(vis,,sizeof(vis));
            f[]=;
            up(i,,LIM){
                  ;}
                  up(j,,cnt){
                        if(i*prime[j]>LIM)break;
                        vis[i*prime[j]]=;
                        ){
                              f[i*prime[j]]=(f[i]*f[prime[j]])%mod;
                        }else{
                              f[i*prime[j]]=(f[i]*g[j])%mod;
                              break;
                        }
                  }
            }
            up(i,,LIM)f[i]=(f[i-]+f[i])%mod;
      }
      void slove(ll a,ll b){
            ll ans=,pos;
            if(a>b)swap(a,b);
            up(i,,a){
                  pos=min(a/(a/i),b/(b/i));
                  ans+=(((f[pos]+mod-f[i-])*(a/i))%mod)*(b/i);
                  ans%=mod;
                  i=pos;
            }
            printf("%lld\n",ans);
      }
}
int main(){
      freopen("input.in","r",stdin);
      using namespace solution;
      T=read();K=read();
      pret();
      while(T--)slove(read(),read());
      ;
}

BZOJ 2154

数论好坑啊
做这道题是为了做下一道题,这道题是下一道题的弱化版..但是我调试了几乎一个上午。
给定N,M求N,M内的lcm累加和。
下面是公式时间:
 


 然后双重分块就好了

这个调试的真恶心...

//BZOJ 2154
//by Cydiater
//2016.7.27
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <iomanip>
#include <queue>
#include <map>
#include <ctime>
#include <cmath>
#include <algorithm>
#include <cstdlib>
using namespace std;
#define ll long long
#define up(i,j,n)       for(ll i=j;i<=n;i++)
#define down(i,j,n)     for(ll i=j;i>=n;i--)
;
const ll LIM=1e7;
;
const ll oo=0x3f3f3f3f;
inline ll read(){
      ,f=;
      ;ch=getchar();}
      +ch-';ch=getchar();}
      return x*f;
}
ll prime[MAXN],cnt=,mu[MAXN],N,M;
bool vis[MAXN];
namespace solution{
      void pret(){
            memset(vis,,sizeof(vis));
            memset(mu,,sizeof(mu));
            mu[]=;
            up(i,,N){
                  ;}
                  up(j,,cnt){
                        if(prime[j]*i>N)break;
                        vis[prime[j]*i]=;
                        ){
                              mu[i*prime[j]]=-mu[i];
                        }else{
                              mu[i*prime[j]]=;
                              break;
                        }
                  }
            }
            up(i,,N)mu[i]=(mu[i-]+(mu[i]*i*i)%mod)%mod;
      }
      ll sum(ll a,ll b){
            )*a/%mod)*(b*(b+)/%mod)%mod;
      }
      ll F(ll a,ll b){
            ll pos,ans=;
            if(a>b)swap(a,b);
            up(i,,a){
                  pos=min(a/(a/i),b/(b/i));
                  ans=(ans+(mu[pos]-mu[i-])*sum(a/i,b/i))%mod;
                  i=pos;
            }
            return ans;
      }
      void slove(ll a,ll b){
            if(a>b)swap(a,b);
            ll pos,ans=;
            up(i,,a){
                  pos=min(a/(a/i),b/(b/i));
                  ans=(ans+(i+pos)*(pos-i+)/%mod*F(a/i,b/i)%mod)%mod;
                  i=pos;
            }
            printf("%lld\n",(ans+mod)%mod);
      }
}
int main(){
      freopen("input.in","r",stdin);
      using namespace solution;
      N=read();M=read();
      if(N>M)swap(N,M);
      pret();
      slove(N,M);
      //cout<<"Time has passed:"<<1.0*clock()/1000<<"s!"<<endl;
      ;
}

BZOJ 2693:

这些数论题套路很多啊..
接着上一个公式:
//BZOJ 2693
//by Cydiater
//2016.7.29
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <queue>
#include <map>
#include <cstdlib>
#include <iomanip>
using namespace std;
#define ll long long
#define up(i,j,n)       for(ll i=j;i<=n;i++)
#define down(i,j,n)     for(ll i=j;i>=n;i--)
;
const int LIM=1e7;
;
const int oo=0x3f3f3f3f;
inline ll read(){
      ,f=;
      ;ch=getchar();}
      +ch-';ch=getchar();}
      return x*f;
}
ll f[MAXN],prime[MAXN],cnt=,T;
bool vis[MAXN];
namespace solution{
      void pret(){
            memset(vis,,sizeof(vis));
            f[]=;
            up(i,,LIM){
                  if(!vis[i]){prime[++cnt]=i;f[i]=(i-i*i%mod)%mod;}
                  up(j,,cnt){
                        if(prime[j]*i>LIM)break;
                        vis[prime[j]*i]=;
                        ){
                              f[i*prime[j]]=(f[i]*prime[j])%mod;
                              break;
                        }
                        f[i*prime[j]]=(f[prime[j]]*f[i])%mod;
                  }
            }
            up(i,,LIM)f[i]=(f[i]+f[i-])%mod;
      }
      ll sum(ll a,ll b){
            ll tmp1=(a*(a+)/)%mod;
            ll tmp2=(b*(b+)/)%mod;
            return (tmp1*tmp2)%mod;
      }
      void slove(ll a,ll b){
            if(a>b)swap(a,b);
            ll pos,ans=;
            up(i,,a){
                  pos=min(a/(a/i),b/(b/i));
                  ans=(ans+(f[pos]-f[i-])*sum(a/i,b/i)%mod)%mod;
                  i=pos;
            }
            printf("%lld\n",(ans+mod)%mod);
      }
}
int main(){
      //freopen("input.in","r",stdin);
      using namespace solution;
      T=read();
      pret();
      while(T--)slove(read(),read());
      ;
}

Mobius 反演的更多相关文章

  1. SPOJ PGCD (mobius反演 + 分块)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题意 :求满足gcd(i , j)是素数(1 &l ...

  2. 关于Mobius反演

    欧拉函数 \(\varphi\) \(\varphi(n)=\)表示不超过 \(n\) 且与 \(n\) 互质的正整数的个数 \[\varphi(n)=n\cdot \prod_{i=1}^{s}(1 ...

  3. mobius反演讲解

    mobius反演的基本形式为,假设知道函数F(x)=Σf(d) d|x,那么我们可以推出f(x)=Σmiu(d)*F(x/d) d|x,另一基本形式为假设知道函数F(x)=Σf(d) x|d,那么我们 ...

  4. [基本操作] Mobius 反演, Dirichlet 卷积和杜教筛

    Dirichlet 卷积是两个定义域在正整数上的函数的如下运算,符号为 $*$ $(f * g)(n) = \sum_{d|n}f(d)g(\frac{n}{d})$ 如果不强调 $n$ 可简写为 $ ...

  5. Mobius反演与积性函数前缀和演学习笔记 BZOJ 4176 Lucas的数论 SDOI 2015 约数个数和

    下文中所有讨论都在数论函数范围内开展. 数论函数指的是定义域为正整数域, 且值域为复数域的函数. 数论意义下的和式处理技巧 因子 \[ \sum_{d | n} a_d = \sum_{d | n} ...

  6. Mobius 反演与杜教筛

    积性函数 积性函数 指对于所有互质的整数 aaa 和 bbb 有性质 f(ab)=f(a)f(b)f(ab)=f(a)f(b)f(ab)=f(a)f(b) 的数论函数. 特别地,若所有的整数 aaa ...

  7. Mobius反演学习

    这篇文章参考了许多资料和自己的理解. 先放理论基础. 最大公约数:小学学过,这里只提一些重要的公式: $·$若$a=b$,则$\gcd(a,b)=a=b$: $·$若$\gcd(a,b)=d$,则$\ ...

  8. Note -「Mobius 反演」光速入门

    目录 Preface 数论函数 积性函数 Dirichlet 卷积 Dirichlet 卷积中的特殊函数 Mobius 函数 & Mobius 反演 Mobius 函数 Mobius 反演 基 ...

  9. 【莫比乌斯反演】关于Mobius反演与gcd的一些关系与问题简化(bzoj 2301 Problem b&&bzoj 2820 YY的GCD&&BZOJ 3529 数表)

    首先我们来看一道题  BZOJ 2301 Problem b Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd( ...

  10. (暂时弃坑)(半成品)ACM数论之旅18---反演定理 第二回 Mobius反演(莫比乌斯反演)((づ ̄3 ̄)づ天才第一步,雀。。。。)

    莫比乌斯反演也是反演定理的一种 既然我们已经学了二项式反演定理 那莫比乌斯反演定理与二项式反演定理一样,不求甚解,只求会用 莫比乌斯反演长下面这个样子(=・ω・=) d|n,表示n能够整除d,也就是d ...

随机推荐

  1. getContentResolver()内容解析者查询联系人、插入联系人

    首先,我们需要知道的两个Uri: 1.Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");//查到 ...

  2. 关于提高python程序执行效率的思路和想法

    相比编译型语言(C系列)python胜在简介的语法和优雅的动态编程体验,但是在执行效率上,python有解释性语言先天的劣势——执行效率较低,为了让编写出的程序获得更快的执行效率,开启此文章. pyt ...

  3. Android下的数据储存方式(三)

      Android下最好的数据储存方式:关系型数据库sqlite.   数据库的创建:使用SqliteOpenHelper类 结合SqliteOpenHelper类和SQLiteDatabase类的帮 ...

  4. SpringMVC学习--json

    简介 json数据格式在接口调用中.html页面中较常用,json格式比较简单,解析还比较方便.比如:webservice接口,传输json数据. springmvc与json交互 @RequestB ...

  5. Angularjs做的一个小页面

    <!DOCTYPE html><html lang="en" ng-app="todolist"> <head> <m ...

  6. linux core dump 文件 gdb分析

    core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump. (linux中如果内存越界会收到SIG ...

  7. SwipeRefreshLayout 首次打开出现加载图标

    最近要实现如何如图效果: 主要是在初始化,代码如下: , getResources().getDimensionPixelSize(typed_value.resourceId));    refre ...

  8. mysql优化基础

    唯一索引(unique index)强调唯一,就是索引值必须唯一. create unique index [索引名] on 表名 (列名);alter table 表名 add unique ind ...

  9. Mustache 使用总结

    前言: 在分析 jeesite 项目的时候,看到了 Mustache,于是查了下 正文: 1.Mustache 概述 Mustache 是基于 JavaScript 实现的模板引擎,即用来 渲染前台页 ...

  10. java基础3.0:Java常用API

    本篇介绍Java基础中常用API使用,当然只是简单介绍,围绕重要知识点引入,巩固开发知识,深入了解每个API的使用,查看JavaAPI文档是必不可少的. 一.java.lang包下的API Java常 ...