Mobius函数计算 定义+代码模板

20 篇文章 1 订阅
7 篇文章 0 订阅

Mobius函数定义为,输入一个正整数N,当N=1时,函数值为1,当N不为1时,首先在稿纸上将它分解质因数,若某质因数的个数大于1,则函数值为0,如N=45,45=3*3*5,3出现了两次,故函数值为0。若质因数全都不相同,设有p个,则函数值为(-1)的p次方,如78,78=2*3*13,质因数全都不相同,有3个,所以函数值为(-1)的3次方,为-1。

f(n)和g(n)是定义在正整数集合上的两个函数,若
  

  
反之亦然。
  其中
  μ(d)=1, 若d=偶数个不同素数之积
  μ(d)=(-1) r, 若d=奇数个不同素数之积
  μ(d)=0, 其他
例如:
μ( 30) = μ( 2·3·5 ) = (-1) 3
μ(12) = μ( 3·2 2) = 0
对任何素数p,μ(p)=-1

辅助定理

编辑
对于任意正整数n,恒有
  
代码模板:

#include <stdio.h>
// 一个数字可以有的最多不同质因数个数 
#define MAX_PRIM_FACTOR_AMOUNT 1000 

/*
Mobius 函数定义为:
    输入一个正整数N,当N=1时,函数值为1,
    
    当N不为1时,首先在稿纸上将它分解质因数。
    若某质因数的个数大于1,则函数值为0,
    如N=45,45=3*3*5,3出现了两次,故函数值为0。
    
    若质因数全都不相同,设有p个,则函数值为(-1)的p次方,
    如78,78=2*3*13,质因数全都不相同,有3个,所以函数值为(-1)的3次方,为-1。
*/
/*
    功能:求  Mobius 函数的值
    参数:
        n        一个正整数  
        doPrint    是否输出正整数 n 的质因数分解形式。1:输出;0:不输出。 
         
    返回: 
        Mobius 函数的值
*/
int Mobius(unsigned int n, unsigned int doPrint)
{
    // 用 m 来临时保存 m 的值。因此 n 的值在运算过程中会被改变。 
    int m = n; 
    // 用 i 来枚举 n 的质因数
    int i;
    // 数字 n 的不同质因数个数 
    int primeFactorAmount = 0;
    // n 的某个质因数 i,出现在 n 中的次数 
    int countCurrentPrimeFactor = 0;
    // Mobius 函数的值。初始值为 -3,表示还没有计算出函数值。 
    int result = -3;
    
     // 记录所有质因数出现的次数。用于输出质因数分解形式。 
     int primFactors[MAX_PRIM_FACTOR_AMOUNT][2]; 
     
    if(n == 0)
    {// 【1】n==0 的情况,实际是非法的输入。这里返回 -2。 
        result = -2;
    }
    else if(n == 1)
    {// 【2】n==1 的情况
        result = 1;
    }
    else
    {
        for(i=2; i<=n ; i++)
        {
            countCurrentPrimeFactor = 0;
            while(n % i == 0)
            {
                // 从数字 n 中除去质因数 i 
                n /= i;
                // 统计质因数 i 出现的次数 
                countCurrentPrimeFactor ++;
            }
            
            if(countCurrentPrimeFactor >= 1)
            {// 数字 i 是数字 n 的质因数 
                primFactors[primeFactorAmount][0] = i;
                primFactors[primeFactorAmount][1] = countCurrentPrimeFactor;
                primeFactorAmount ++;
                
                if(countCurrentPrimeFactor > 1)
                {// 【3】 n 的某质因数的个数大于 1 的情况 
                    result = 0;
                }                
            }
        }
                
        if(result == -3)
        {// 【4】 n 有 p 个不同的质因数,返回 (-1)^p 
            result = (primeFactorAmount%2 ? -1 : 1);    
        }        
    }
    
    if(doPrint)
    {// 需要输出 n 的质因数分解形式
        if(m <= 1)
            printf("%d = %d\n", m , m);
        else
        {
            printf("%d = ", m);
            for(i=0; i<primeFactorAmount; i++)
            {
                printf("%d", primFactors[i][0]);
                if(primFactors[i][1] > 1)
                // 质因数出现多余一次,输出出现次数。 
                    printf("^%d", primFactors[i][1]);
                
                if(i < (primeFactorAmount-1))
                    printf(" * ");
            }
            printf("\n");
        }      
    } 
    
    return result;

}
int main(int argc, char *argv[])
{
    int n;
    // 输入 n ,按 ctrl + z 停止输入 
    while(scanf("%d",&n) !=EOF)
    {
        printf("Mobius(%d) = %d\n", n, Mobius(n, 1));
    } 
    return 0;
}

/*
测试数据:
0
1
45
78 
12345678

测试结果:
0
0 = 0
Mobius(0) = -2
1
1 = 1
Mobius(1) = 1
45
45 = 3^2 * 5
Mobius(45) = 0
78
78 = 2 * 3 * 13
Mobius(78) = -1
12345678
12345678 = 2 * 3^2 * 47 * 14593
Mobius(12345678) = 0
^Z 
*/


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值