一些有用的数论知识。(莫比乌斯反演)

先讲一下原根的一些小知识。。

原根的意思是,对于一个质数p,若一个正整数a,有且只有a^(p - 1) mod p = 1,则称a为p的原根

原根的性质:(有空可以看一下http://www.infosec.sdu.edu.cn/jpkc/resource/4yuangen.pdf)

怎么找原根:?

p的原根数量=φ(φ(m))

     若a为p的原根,则对于质数pi | (p-1),a^((p-1)/pi) mod p != 1


莫比乌斯反演。

设函数f,g,我们定义一种新运算f*g,表示

(f*g)(n) = 


定义函数μ(n),



莫比乌斯反演公式:g= f*1 ---> f = μ*g

同时,运算*满足交换律与结合律,这也是我们用来解决数学问题的强力工具!!!


来一道比较简单的例题吧。。

比如说,求φ(m)的值。

再比如说,求(spoj gcdex)


我这里就直接贴结论好了。。f = μ * id * id


积性函数的性质:若f,g为积性函数,则h(n)=f(n)*g(n),h也为积性函数

若f = μ*g,f或g为积性函数,则另一个也是积性函数。


相关的例题,SDOI2014数表,spoj PGCD,spoj LCMSUM

推荐的论文:贾志鹏的《线性筛法与积性函数 》

相关的代码:


spoj gcdex

#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      

using namespace std;

typedef long long LL;

const int MAXN = 1000005;

LL F[MAXN];
int Zh[MAXN],Muti[MAXN],ti[MAXN],fai[MAXN],N,tot;
bool bz[MAXN];

void Pre_Treat()
{
	N = MAXN - 5;
	for(int i = 2;i <= N;i ++)
	{
		if (!bz[i]) Zh[++ tot] = i,Muti[i] = i,fai[i] = i - 1;
		for(int j = 1;j <= tot;j ++)
		if (LL(i) * Zh[j] > N) break; else
		{
			bz[i * Zh[j]] = 1;
			if (i % Zh[j] == 0)
			{
				int least = i / Muti[i];
				if (least == 1) fai[i * Zh[j]] = i * (Zh[j] - 1); else
				fai[i * Zh[j]] = fai[least] * fai[Muti[i] * Zh[j]];
				Muti[i * Zh[j]] = Muti[i] * Zh[j];
				break;
			}
			fai[i * Zh[j]] = fai[i] * fai[Zh[j]],Muti[i * Zh[j]] = Zh[j];
		}
	}
	for(int i = 1;i <= N;i ++) F[i] = fai[i];
	for(int i = 2;i * i <= N;i ++)
	{
		F[i * i] += i * LL(fai[i]);
		for(int j = i + 1;j * i <= N;j ++)
		F[i * j] += i * LL(fai[j]) + LL(fai[i]) * j;
	}
	for(int i = 1;i <= N;i ++) F[i] += F[i - 1];
}

int main()
{
	Pre_Treat();
	while (scanf("%d", &N) != EOF && N) printf("%lld\n",F[N]);
}


     
     
    
    
   
   




spoj PGCD

#include
   
   
    
    
#include
    
    
     
     

using namespace std;

const int MAXN = 10000005;

bool bz[MAXN];
int Zh[MAXN],g[MAXN],u[MAXN],tot;

int min(int a,int b) {return a < b ? a : b;}

void Pre()
{
	int N = MAXN - 5;
	u[1] = 1;
	for(int i = 2;i <= N;i ++)
	{
		if (!bz[i]) Zh[++ tot] = i,u[i] = -1,g[i] = 1;
		for(int j = 1;j <= tot;j ++)
		if (i * (long long)Zh[j] > N) break;else
		{
			bz[i * Zh[j]] = 1;
			if (i % Zh[j] == 0) {g[i * Zh[j]] = u[i];break;}
			u[i * Zh[j]] = u[i] * -1;
			g[i * Zh[j]] = u[i] - g[i];
		}
	}
	for(int i = 1;i <= N;i ++) g[i] += g[i - 1];
}

int main()
{
	Pre();
	int T,cnt = 0;scanf("%d", &T);
	long long Ans = 0;
	for(;T;T --)
	{
		int a,b;
		Ans = 0;
		scanf("%d%d", &a, &b);
		int h = min(a,b);
		for(int i = 1;i <= h;)
		{
			int ta = a / i,tb = b / i;
			int j = min(a / ta,b / tb);
			Ans += ta * (long long)tb * (g[j] - g[i - 1]);
			i = j + 1;
		}
		printf("%lld\n", Ans);
	}
}
 

    
    
   
   




spoj LCMSUM
#include
    
    
     
     

using namespace std;

const int MAXN = 1000005;

bool bz[MAXN];
int prime[MAXN],Ask[300005],h[MAXN],N;
long long f[MAXN];

long long sqr(int a) {return (long long)a * a;}

void Pre_Treat()
{
	f[1] = 1;int tot = 0,k;
	for (int i = 2;i <= N;i ++)
	{
		if (!bz[i]) h[i] = i,prime[++ tot] = i,f[i] = sqr(i) - i + 1;
		for (int j = 1;j <= tot;j ++)
			if ((k = prime[j] * i) > N) break; else
			{
				bz[k] = 1;
				if (!(i % prime[j]))
				{
					if (i != h[i]) f[k] = f[i  / h[i]] * f[h[i] * prime[j]];
					else
						f[k] = (sqr(k) * prime[j] - prime[j]) / (prime[j] + 1) + 1;
						h[k] = h[i] * prime[j];
					break;
				} 
				else
					f[k] = f[prime[j]] * f[i],h[k] = prime[j];
			}
	}
}

void read(int &a)
{
	a = 0;char c;
	while (c = getchar(),c < '0' || c > '9');
	a = c - 48;
	while (c = getchar(),c >= '0' && c <= '9') a = a * 10 + c - 48;
}

int main()
{
	int T;read(T);
	for (int i = 1;i <= T;i ++) {read(Ask[i]);if (Ask[i] > N) N = Ask[i];}
	Pre_Treat();
	for (int i = 1;i <= T;i ++) printf("%lld\n",(f[Ask[i]] + 1) * Ask[i] / 2);
}


    
    



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值