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, 其他
其中
μ(d)=1, 若d=偶数个不同素数之积
μ(d)=(-1)r, 若d=奇数个不同素数之积
μ(d)=0, 其他
例如:
μ( 30) = μ( 2·3·5 ) = (-1)3
μ(12) = μ( 3·22) = 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 */