zoukankan      html  css  js  c++  java
  • (暂时弃坑)(半成品)ACM数论之旅18---反演定理 第二回 Mobius反演(莫比乌斯反演)((づ ̄3 ̄)づ天才第一步,雀。。。。)

    莫比乌斯反演也是反演定理的一种

    既然我们已经学了二项式反演定理

    那莫比乌斯反演定理与二项式反演定理一样,不求甚解,只求会用

    莫比乌斯反演长下面这个样子(=・ω・=)

    莫比乌斯反演1

    d|n,表示n能够整除d,也就是d是n的所有因子

    μ(x)是莫比乌斯函数,它是这样计算的

    μ(1) = 1 

    x = p1 * p2 * p3 ……*pk(x由k个不同的质数组成)则μ(x) = (-1)^k 

    其他情况,μ (x) = 0 

    比如

    30 = 2 * 3 * 5

    μ(30) = (-1)^3 

    4 = 2 * 2

    μ(4) = 0

    对于μ(d)函数,它有如下的常见性质:

        (1)对任意正整数n有

    莫比乌斯反演2

        (2)对任意正整数n有 

     莫比乌斯反演3

    求μ的函数的方法很多

    这里提供一种线筛的预处理(复杂度O(n)哟~~~)

     1 #include<cstdio>
     2 const int N = 1e6 + 5;
     3 int mu[N], vis[N], prime[N];
     4 int tot;//用来记录prime的个数
     5 void init(){
     6     mu[1] = 1;
     7     for(int i = 2; i < N; i ++){
     8         if(!vis[i]){
     9             prime[tot ++] = i;
    10             mu[i] = -1;
    11         }
    12         for(int j = 0; j < tot && i * prime[j] < N; j ++){
    13             vis[i * prime[j]] = 1;
    14             if(i % prime[j]) mu[i * prime[j]] = -mu[i];
    15             else{
    16                 mu[i * prime[j]] = 0;
    17                 break;
    18             }
    19         }
    20     }
    21 }
    22 int main(){
    23     init();
    24 }

     上次,有人问我μ为啥不是miu是mu

    这。。。当然都可以啦,μ的英文就是mu,miu是读音看你习惯

    ∑(っ °Д °;)っ为了证明我是对的,我特意百度了希腊字母读音及科学方面应用

    大写
    小写
    英文读音
    国际音标
    意义
    Α
    α
    alpha
    /ˈ&aelig;lfə/
    角度,系数,角加速度
    Β
    β
    beta
    /'beitə/
    磁通系数,角度,系数
    Γ
    γ
    gamma
    /'g&aelig;mə/
    电导系数,角度,比热容比
    Δ
    δ
    delta
    /'deltə/
    变化量,屈光度,一元二次方程中的判别式
    Ε
    ε
    epsilon
    /ep'silon/
    对数之基数,介电常数
    Ζ
    ζ
    zeta
    /'zi:tə/
    系数,方位角,阻抗,相对粘度
    Η
    η
    eta
    /'i:tə/
    迟滞系数,效率
    Θ
    θ
    theta
    /'θi:tə/
    温度,角度
    Ι
    ι ℩
    iota
    /ai'oute/
    微小,一点
    Κ
    κ
    kappa
    /k&aelig;pə/
    介质常数,绝热指数
    λ
    lambda
    /'l&aelig;mdə/
    波长,体积,导热系数
    Μ
    μ
    mu
    /mju:/
    磁导系数,微,动摩擦系(因)数,流体动力粘度
    Ν
    ν
    nu
    /nju:/
    磁阻系数,流体运动粘度,光子频率
    Ξ
    ξ
    xi
    /ksi/
    随机数,(小)区间内的一个未知特定值
    Ο
    ο
    omicron
    /oumaik'rən/
    高阶无穷小函数
    π
    pi
    /pai/
    圆周率,π(n)表示不大于n的质数个数
    Ρ
    ρ
    rho
    /rou/
    电阻系数,柱坐标和极坐标中的极径,密度
    σ ς
    sigma
    /'sigmə/
    总和,表面密度,跨导,正应力
    Τ
    τ
    tau
    /tau/
    时间常数,切应力
    Υ
    υ
    upsilon
    /ju:p'silən/
    位移
    Φ
    φ
    phi
    /fai/
    磁通,角,透镜焦度,热流量
    Χ
    χ
    chi
    /kai/
    统计学中有卡方(χ^2)分布
    Ψ
    ψ
    psi
    /psai/
    角速,介质电通量
    Ω
    ω
    omega
    /'oumigə/
    欧姆,角速度,交流电的电角度

    其实莫比乌斯有两种描述

    莫比乌斯反演一

    莫比乌斯第一种描述,一般是这种

    莫比乌斯反演二

    莫比乌斯第二种描述,这种也可以而且有些题这种更好

    来做题吧

    hdu 1695

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

    (这题就是容斥那一章的,我就把下面的题意照搬过来了,还记得题目的就跳过题目吧) 

    题意:给你5个数a,b,c,d,k

    在a~b中选一个x, c~d中选一个y,满足gcd(x,y) = k , 求(x,y) 的对数 

    a, b, c, d, k, 0 < a <= b <= 100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000

    在题目描述的最后一行有一句话,多组里面所有的a和c都是1(这题目不是坑爹吗(╯‵□′)╯︵┻━┻那输入a和c有什么用)

    然后题目变成

    在1~b中选一个x, 1~d中选一个y,满足gcd(x,y) = k , 求(x,y) 的对数 。。。(无语中。。。)

    前面思路一样

    先把问题就转化为求1~a区间 和 1~b区间,gcd(x,y) = 1对数的问题

    设f(d)为满足gcd(x,y)=d的x,y的对数

    我们根据莫比乌斯第二描述来做

    那F(1) = f(1) + f(2) + f(3) + ....

    F(2) = f(2) + f(4) + f(6) +.....

    我们可以看出F(d)就是满足gcd(x,y)为d的倍数的x,y的对数

    那F(d)的公式就容易求了

    F(d) = (a/d) * (b/d)

    (在1~a中,有a/d个数是d的倍数,在1~b中,有b/d个数是d的倍数,这些数不管怎么选择,构成的gcd(x,y)都是d的倍数)

    因为

     F(1) = f(1) + f(2) + f(3) + ....

    所以

    f(1) = μ(1)*F(1) + μ(2)*F(2) + μ(3)*F(3) + ...

    AC代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 typedef long long LL;
     5 const int N = 1e6 + 5;
     6 int mu[N], vis[N], prime[N];
     7 int tot;//用来记录prime的个数
     8 void init(){
     9     mu[1] = 1;
    10     for(int i = 2; i < N; i ++){
    11         if(!vis[i]){
    12             prime[tot ++] = i;
    13             mu[i] = -1;
    14         }
    15         for(int j = 0; j < tot && i * prime[j] < N; j ++){
    16             vis[i * prime[j]] = 1;
    17             if(i % prime[j]) mu[i * prime[j]] = -mu[i];
    18             else{
    19                 mu[i * prime[j]] = 0;
    20                 break;
    21             }
    22         }
    23     }
    24 }
    25 LL Mobius(int a, int b){
    26     LL ret = 0;
    27     for(int i = 1; i <= a; i ++){//因为公式中有a/i,所以for到a就可以了 
    28         ret += 1ll * mu[i] * (a / i) * (b / i);
    29     }
    30     //我们现在求完了总对数,但是题目要求的类似(5,7)和(7,5)算一种
    31     //所以接下来我们开始去重
    32     LL temp = 0;
    33     for(int i = 1; i <= a; i ++){
    34         temp += 1ll * mu[i] * (a / i) * (a / i);
    35     } 
    36     return ret - temp / 2;
    37     //比如a=5,b=7那么(4,6)这样子的区间不可能有重复的(6,4)
    38     //所以重复的部分只在1~a中,所以最后减去一半的重复区间就好了 
    39 }
    40 int main(){
    41     init();
    42     int T, a, b, c, d, k;
    43     scanf("%d", &T);
    44     for(int cas = 1; cas <= T; cas ++){
    45         scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
    46         if(k == 0){
    47             printf("Case %d: 0
    ", cas);
    48             continue;
    49         }
    50         b /= k; d /= k;
    51         if(b > d) swap(b, d);
    52         printf("Case %d: %I64d
    ", cas, Mobius(b, d));
    53     }
    54 }
    View Code

    /////////////////此处施工中//////////////////

    暂时弃坑。。。。

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=94200#overview

    峰神挂的莫比乌斯反演章节,有兴趣自己去做做,不会的去百度。。。。

  • 相关阅读:
    MyBatis 核心配置综述之 ResultSetHandler
    MyBatis 核心配置综述之 ParameterHandler
    MyBatis 核心配置综述之StatementHandler
    高等数学——手撕牛顿莱布尼茨公式
    用二分法优化动态规划——实现快速决策
    召回、精确、准确,这些让人头大的概念一文全讲清楚
    Python——详解__slots__,property和私有方法
    LeetCode50——一题学会快速幂算法
    Golang——详解Go语言代码规范
    spark——详解rdd常用的转化和行动操作
  • 原文地址:https://www.cnblogs.com/linyujun/p/5210772.html
Copyright © 2011-2022 走看看