欧拉函数
欧拉定理:
对于互质的整数a和n,有aφ(n) ≡ 1 mod n ( ≡ 同于符号)。证明略过。
费马小定理 a^(p-1) ≡ 1(mod p,p是质数,所以φ(p) = p - 1); 对于不能被质数p整除的正整数a,有ap ≡ a mod p
1)互质:
1.定义
互质: 又叫互素。若n个整数的最大公因数是1,则称这n个整数互质。(1和任何数都互质)。
2.判断方法
(1)2个不同的质数一定是互质数。
(2)一个质数,另一个不为它的倍数,这两个数一定互质。
(3)1不是质数也不是合数,它和任何一个自然数在一起都是互质数。
(4)相邻的两个自然数是互质的。如15 和 16
(5)相邻的两个奇数都是互质的。如49 和 51
(6)较大数是质数的两个数互质。根据(2)得到
(7)两个数都是合数(差较大),较小数所有的质因数,都不是较大数的约数,这两个数是互质数。如357 和 715, 357 = 3 * 7 * 17,而3、7和17都不是715的约数,这两个数互质。
(8)两个数都是合数(差较小),这两个数的差的所有质因数都不是较小数的约数,这两个数是互质数。如85 和 78。85 - 78 = 7, 7不是78的约数,这两个数是互质数。
(9)两个数都是合数,较大数除以较小数的余数(不为0且大于1)的所有的质因数,都不是较小数的约数,这连个数互素。
2)欧拉函数:
1.基本内容
对于正整数n,欧拉函数是少于或等于n的数中与n互质的数的数目。如 φ(8) = 4,因为1 3 5 6都与8互质。
通式: φ(x) = x*(1-1/p1) *(1-1/p2)*(1-1/p3)*(1-1/p4)*...*(1-1/pn);其中p1,p2,...pn为x的所有的质因数,x是不为0的整数。 φ(1) = 1;
(1)p^k的欧拉函数
对于给定的一个素数p,φ(p) = p - 1。则对于正整数n = p^k
(n是质数p 的倍数),φ(n) = p^k - p^(k-1)。
(2)p * q的欧拉函数
假设p,q是2个互质的正整数,则p*q的欧拉函数为φ(p * q) = φ(p)*φ(q);
gcd(p,q) = 1。
(3)任意正整数的欧拉函数
Φ(n) = ∏ piki -1(pi -1) = n ∏ (1 - 1 / pi)
i=1 i=1
对于任意 n > 2,2 | Φ(n) ,因为必存在 pi -1 是偶数。
∏表示连乘符号。
设a为N的质因数,若(N % a == 0 && (N / a) % a == 0) 则有E(N)=E(N / a) * a;若(N % a == 0 && (N / a) % a != 0) 则有:E(N) = E(N / a) * (a - 1)。
2.模板:
int ef(int n) { int cnt=n; int i; for(i=2;i<=n;i++) if(n%i==0) { cnt - =cnt/i; // (x-x/p1) *(1-1/p2)*(1-1/p3)*(1-1/p4)..... while(n%i==0) n/=i; } return cnt; }
求2 ~ n每个数的欧拉函数。
#include<map> #include<set> #include<string> #include<queue> #include<stack> #include<cmath> #include<vector> #include<cstdio> #include<time.h> #include<cstring> #include<iostream> #include<algorithm> #define INF 1000000001 #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int MAXN = 5000010; int isnotprime[MAXN],prime[MAXN],cnt; int er[MAXN]; int L,R; void Init() { cnt = 0; memset(er,0,sizeof(er)); memset(isnotprime,0,sizeof(isnotprime)); for(int i = 2; i < MAXN; i++){ if(!isnotprime[i]){ er[i] = i - 1; prime[cnt++] = i; } for(int j = 0; j < cnt && 1LL * i * prime[j] < MAXN; j++){ isnotprime[i * prime[j]] = 1; if(i % prime[j] == 0){ er[i * prime[j]] = er[i] * prime[j]; break; } else { er[i * prime[j]] = er[i] * (prime[j] - 1); } } } } int main() { Init(); while(~scanf("%d%d",&L,&R)){ int ans,num; ans = L; num = er[L]; for(int i = L + 1; i <= R; i++){ if(er[i] < num){ num = er[i]; ans = i; } } cout<<ans<<endl; } return 0; }