数论学习笔记 欧拉函数 (一些性质和运用)内置杜教筛
2016-09-01 15:31
393 查看
定义
在数论中,对正整数n,欧拉函数是小于等于n的数中与n互质的数的数目。并且用符号φ(n)表示一个整数的欧拉函数。例如φ(8)=4。特殊的φ(1)=1。一些欧拉函数的性质
性质一
对于一个质数n,φ(n)=n−1。证明:
因为n是质数。
性质二
若n=pk,则φ(n)=pk−pk−1=(p−1)pk−1。证明:
因为除了p的倍数外,其他数都跟n互质。
性质三
当gcd(n,m)=1时,φ(nm)=φ(n)∗φ(m)证明:
φ(n)是积性函数。
性质四
设n=pk11∗pk22...∗pkmm,则φ(n)=n∗(1−1p1)∗(1−1p2)∗...(1−1pm)证明:
根据性质二
φ(n)=∏(pi−1)pki−1i(pi|n)=n∏(1−1p1)(直接把n提出来)
当然也可以用容斥的想法去理解。
性质五
欧拉定理:对于互质的整数a,m有aφ(m)≡1(modm)。证明:
这小于n且与n互质的集合时Z,显然|Z|=φ(n),Z={p1,p2...pφ(n)}。
令集合S={a∗p1modn,a∗p2modn...a∗pφ(n)modn}。
因为:
1. 因为a与n互质,pi与n互质,所以a∗pi与n互质,所以a∗p1modn∈Z
2. 若i≠j,那么a∗pimodn≠a∗pjmodn
反证:
假如a∗pimodn=a∗pjmodn ,设a∗pi=ki∗n+b
那么
a∗pi=ki∗n+b=a∗pj=kj∗n+ba∗(pi−pj)=n∗(ki−kj)
因为a与n互质,即n|(pi−pj),不成立。
所以S=Z。
由此我们可以列出等式:
a∗p1∗a∗p2...∗a∗pφ(n)aφ(n)≡p1∗p2...pφ(n)(modn)≡1(modn)
延伸:
费马定理:如果正整数a与p互质,则ap−1≡1(modp)。
证明:由性质一可得φ(p)=p−1,代入欧拉定理即可
性质六
设小于n的所有与n互质的数的和为Sum,Sum=n∗φ(n)2证明:
首先证明一个结论:如果gcd(n,i)=1则gcd(n,n−i)=1。
反证法:如果存在k≠1使gcd(n,n−i)=k,那么
(n−i)modk=0,nmodk=0
可得imodk=0,即gcd(n,i)=k,也就是说如果gcd(n,i)=1,那么gcd(n,n−i)就不能大于1。
那么就可以得知与n互质的数都是成对存在的,并且和为n,那么就可以得出Sum=n∗φ(n)2的公式。
性质七
首先p是个质数。如果imodp=0,那么φ(i∗p)=p∗φ(i)(结论一),否则φ(i∗p)=φ(i)∗(p−1)(结论二)。证明:
对于第一个结论我们只需证明gcd(n,m)=1可以得出gcd(n,m+n)=1即可。
反证法:假设gcd(n,m+n)=b(b≠1)。设n+m=k1b,m=k2b。
k2b+n=k1bn=(k1−k2)b
所以gcd(n,m)至少等于b。
得证。
对于第二个结论,我们可知由于gcd(i,p)=1,φ(i∗p)=φ(p)∗φ(i),并且φ(p)=p−1(性质一,性质三),得证。
性质八
直接给式子吧…n=∑d|nφ(d)
根据上面那条式子可以继续推点显而易见的东西
∑i=1ni=∑i=1n∑d|iφ(d)=∑d=1nφ(d)∗⌊nd⌋
反演一下,φ(n)=∑d|nμ(d)∗nd
信息学中的应用
应用一:线筛φ函数
这个算法让我们可以在O(n)的时间得出φ(1)~φ(n)的值。首先我们要用到几条上面提到的性质。
1. φ(n)=n−1(性质一)
2. 如果imodp=0,那么φ(i∗p)=p∗φ(i)(性质七)
3. 如果imodp≠0,那么φ(i∗p)=φ(i)∗(p−1)(性质七)
那么根线筛素数的原理一样(积性函数)我们只需根据欧拉函数的性质来进行线筛。
//YxuanwKeith void Getphi(int Max) { phi[1] = 1; for (int i = 2; i <= Max; i ++) { if (!Flag[i]) { phi[i] = i - 1; // i是质数,第一种情况。 pri[++ pri[0]] = i; } for (int j = 1; j <= pri[0]; j ++) { if (1ll * i * pri[j] > Max) break; Flag[i * pri[j]] = 1; //筛质数。 if (i % pri[j] == 0) { phi[i * pri[j]] = phi[i] * pri[j];//(i % pri[j] = 0),第二种情况 break; } phi[i * pri[j]] = phi[i] * (pri[j] - 1); //(i % pri[j] != 0),第三种情况 } } }
应用二:O(n√)得到φ(n)
直接根据性质四,O(n√)的枚举n的所有质因子,然后直接套用公式算,如果n特别打的话还可以选择用millerrabin+pollarrho来找质数。//YxuanwKeith long long Getphi(long long n) { long long phi = n; for (long long i = 2; i * i <= n; i ++) { if (n % i == 0) { phi /= i; phi *= i - 1; while (n % i == 0) n /= i; } } if (n != 1) phi /= n, phi *= n - 1; return phi; }
应用三:杜教筛求φ的前缀和
即求∑ni=1φ(i),n<=101051nod题目连接
由于本文着重讨论欧拉函数的性质,所以就不细讲杜教筛相关内容,有兴趣的可以通过下面的blog了解:
http://blog.csdn.net/skywalkert/article/details/50500009
基本原理:假设我们要计算S(n)=∑ni=1f(i)
∑i=1n(f∗g)(i)=∑i=1n∑d∣ig(d)f(id)=∑d=1ng(d)∑1≤i≤n,d|if(id)=∑d=1ng(d)∑1≤i≤⌊nd⌋f(i)=∑d=1ng(d)S(⌊nd⌋)
∴g(1)S(n)=∑i=1n(f∗g)(i)−∑i=2ng(i)S(⌊ni⌋)
根据杜教筛的应用,设f(i)=φ(i),我们要找到一个函数g(i)使得g(i)的前缀和和f(i)∗g(i)的前缀和都很好求。根据性质八,不难发现f(i)∗1=id(1函数满足各项都为1,id函数满足id(i)=i)。
设ϕ(n)=∑ni=1φ(i),根据杜教筛:
ϕ(n)=∑i=1nφ(i)=∑i=1n⎛⎝i−∑d|i,d<iφ(d)⎞⎠=n⋅(n+1)2−∑i=2n∑d|i,d<iφ(d)=n⋅(n+1)2−∑id=2n∑d=1⎢⎣⎢⎢nid⎥⎦⎥⎥φ(d)=n⋅(n+1)2−∑i=2n∑d=1⌊ni⌋φ(d)=n⋅(n+1)2−∑i=2nϕ(⌊ni⌋)
然后递推进去算就可以了,直接这样算是O(n34),但是由于φ是积性函数,可以预处理出前n23的ϕ然后再做杜教筛,复杂度就优化成了O(n23)
//YxuanwKeith //51nod1239 #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; typedef long long LL; const int MAXN = 5e6 + 5, MAXM = 1e6 + 5; const int Mo = 1e9 + 7; LL n, que[MAXM]; int m, num, pri[MAXN], sum[MAXN], phi[MAXN], ids[MAXM], idl[MAXM], s[MAXM], inv[MAXN]; bool flag[MAXN]; int power(int x, int y) { int ans = 1; for (; y; y >>= 1, x = 1ll * x * x % Mo) if (y & 1) ans = 1ll * ans * x % Mo; return ans; } void prepare() { phi[1] = 1; for (int i = 2; i < MAXN; i ++) { if (!flag[i]) pri[++ pri[0]] = i, phi[i] = i - 1; for (int j = 1; j <= pri[0] && 1ll * i * pri[j] < MAXN; j ++) { int x = i * pri[j]; flag[x] = 1; if (i % pri[j] == 0) { phi[x] = phi[i] * pri[j]; break; } phi[x] = phi[i] * (pri[j] - 1); } } for (int i = 1; i < MAXN; i ++) sum[i] = (sum[i - 1] + phi[i]) % Mo; } int main() { scanf("%lld", &n); prepare(); m = sqrt(n); for (LL l = 1; l <= n; l ++) { LL d = n / l, r = n / d; que[++ num] = d; if (d <= m) ids[d] = num; else idl[l] = num; l = r; } int inv = power(2, Mo - 2); for (int i = num; i; i --) { LL x = que[i]; if (x < MAXN) s[i] = sum[x]; else { int y = x % Mo; s[i] = 1ll * y * (y + 1) % Mo * inv % Mo; for (LL l = 2; l <= x; l ++) { LL p = x / l, r = x / p; p = (p <= m) ? ids[p] : idl[n / p]; (s[i] -= 1ll * (r - l + 1) * s[p] % Mo) %= Mo; l = r; } } } printf("%d\n", (s[1] + Mo) % Mo); }
另外还有一些欧拉函数的变形也可以通过杜教筛来算:
1. f(i)=φ(i)∗i,f(i)∗id=id2
∑d|nd⋅φ(d)⋅nd=n⋅∑d|nφ(d)=n2
这个可以扩展到f(i)=φ(i)∗ik,f(i)∗idk=idk+1
相关文章推荐
- 数论学习笔记 欧拉函数(一些性质和运用)+杜教筛
- 欧拉函数 (一些性质和运用)内置杜教筛
- java学习笔记1——面向对象的一些性质
- Python3.3 学习笔记4 - 函数 - 内置和其他一些函数
- 数论学习笔记之欧拉函数
- freemaker学习笔记--其它内置方法
- 写得蛮好的linux学习笔记(一些常用的基本命令)
- UML学习笔记(三):运用面向对象思想
- 我的设计模式之旅(1)——学习的原则和一些笔记
- java学习笔记(六)----对象的类型转换, 匿名内置类
- 学习java过程中的一些笔记.
- java学习笔记,关于java的一些基础知识,适用于初学者,第一节
- 关于ccna的一些学习笔记
- NetTiers学习笔记04---NetTiers模板中各个选项的一些解释
- Oracle学习时笔记,一些资料
- MyGeneration学习笔记(3) : dOOdads及生成代码的一些bug
- UML学习笔记(三):运用面向对象思想
- 我的智能网学习笔记.一些乱七八糟的东西.
- 最近的学习笔记,记录一些通俗易懂的学习类文章。更像是好资料参与索引。
- [SQL学习笔记之一]SQLServer的内置XML支持