欧拉筛
模板
vector<int> prime;
bool isprime[N];
inline void GetPrime(){
isprime[0] = isprime[1] = 1;
for(int i = 2; i < N; i ++){
if(!isprime[i]) prime.push_back(i);
for(int j = 0; j < prime.size() && prime[j] * i < N; j ++){
isprime[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
算术基本定理
算术基本定理,又称唯一分解定理
定理内容是:
任何一个大于1的自然数N,如果N不为质数,都可以唯一分解成有限个质数的乘积 N=P1a1P2a2...Pnan 。这里 P1<P2<...<Pn 均为质数,指数 ai 均为正整数
这样的分解称为N的标准分解式
在线性筛中的应用:每个数因它最小的质数而被标记
规则体现在:如果某个数num包含了某个div,那么这个最小div可以和别的数凑成一个更大的数去标记,那么此时后面就不需要继续用num去凑数标记了。
例: (i,j)=(4,2),,i%j=0 ,那么说明4中有2,走到后面有个12,12可以因为(6,2)被标记,那么此时就不需要用(4,3)去进行标记了
欧拉函数
概念
i=1∑n[gcd(i,n)=1] ,记为 ϕ(n)
欧拉函数的通式: ϕ(x)=x∗i=1∏n(1−pi1)
欧拉函数的性质: n的因子的欧拉函数加起来等于n
证明
情况1.如果 n 是一个素数:
n=pϕ(n)=n(1−p1)=p(1−p1)=p−1
情况2.如果 n 是一个素数 p 的 α 次幂:
那么从1→n中,只有p的倍数不与n互质,从1到n, p、2p、3p、.....、pα−1p 一共有 pα−1 个
所以 ϕ(n)=n−pα−1=pα−pα−1=pα(1−p1)=n(1−p1)
情况3.如果 n 是两个素数 p q 的乘积:
显然此时与n互质的数既不是 p 的倍数也不是 q 的倍数。类似的情况2中的分析,p的倍数应有q个,q 的倍数有p个,但是还多算了一个既是p也是q的倍数n,于是 ϕ(n)=n−(p+q−1)=p∗q−p−q+1=(p−1)(q−1)=n(1−p1)(1−q1)
还可以发: ϕ(n)=ϕ(p×q)(1−p1)(1−q1)=ϕ(p)×ϕ(q)
概念:积性函数和完全积性函数 (欧拉函数是积性函数)
完全积性函数:ϕ(n)=ϕ(p×q)=ϕ(p)×ϕ(q) 中不要求 p q 互质
积性函数:ϕ(n)=ϕ(p×q)=ϕ(p)×ϕ(q) 中要求 p q 互质
情况4.n 是某个 m 和一个于 m 互质的素数 p 的乘积,即: n=m∗p:(完整的证明需要各种定理,这里不详解)假设 m 是之前讨论的情况,即 m 满足欧拉函数公式:
ϕ(m)=m∗i=1∏k(1−pi1)
同时因为 n=m∗p, m 与 p 互质, 则有:
ϕ(n)=ϕ(m∗p)=ϕ(m)∗ϕ(p)
另外,由情况 1 可知: ϕ(p)=p−1=p(1−p1)
显然, ϕ(m)∗ϕ(p) 得到的公式,依然满足欧拉函数
情况5. n=m∗p, p 是素数,但是 p 不与 m 互质
p 是素数,但不与 m 互质,显然 p 是 m 的因子,可以转化为 n=q×pα=ϕ(q)×ϕ(pα) ,其中 q 不含 p 的因子 故:
ϕ(n)=ϕ(q∗pα)=ϕ(q)∗ϕ(pα)=q∗pα∗i=1∏k(1−pi1)=n∗i=1∏k(1−pi1)
公式显然依然成立
线性求法
for(int i = 2; i <= N; i ++){
if(!vis[i]) prime.push_back(i), phi[i] = i - 1;
for(int j = 0; j < prime.size() && i * p[j] <= N; j ++){
vis[i * prime[j]] = 1;
if(i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j]; break; }
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
1
2
3
4
5
6
7
8
欧拉定理
概念
若 n, a 为正整数,且它们互质,则
aϕ(n)≡1(modn)
显然:当 n 为质数时 an−1≡1(modn) 就是费马小定理
应用 —— 逆元
如果在模运算中有除法,同时模数不是质数,则此时不可以用费马小定理,可以用欧拉定理
逆元就相当于把费马小定理中的质数一般化一下: a 的逆元 = aϕ(n)−1
扩展欧拉定理
概念
用来降幂,又称为欧拉降幂
ab≡⎩⎪⎨⎪⎧ab%ϕ(n)aab%ϕ(n)+ϕ(n)gcd(a,n)=1gcd(a,n)=1,b<ϕ(n)(modn)gcd(a,n)=1,b≥ϕ(n)
程序实现
int main(){
while(scanf("%lld%s%lld", &a, b, &n) == 3){
ll len = strlen(b), p = phi(c), up = 0;
for(ll i = 0; i < len; i ++) up = (up * 10 + b[i] - '0') % p;
up += p;
outLL(ksm(a, up, n));
}
}
1
2
3
4
5
6
7
8
例题
给定一个长度为n的数组以及若干次询问 l,r.
求: alal+1al+2...armodm
解:使用欧拉降幂递归求指数:
inline ll get(ll l, ll r, ll m){
if(l == r || m == 1) return mo(a[l], m);
return ksm(a[l], get(l + 1, r, phi(m)), m);
}
1
2
3
4
T组询问,每次询问给出一正整数 p(p <= 1e7), 求 222...2modp
递归层数会不会很大?
欧拉函数两个性质:
(1)p>2时, ϕ(p) 为偶数
(2)p如果为偶数, ϕ(p)≤2p
可以证明:递归层数为 O(logp)