线性筛prime/phi/miu/求逆元模板
这绿题贼水......
原理我不讲了,随便拿张草稿纸推一下就明白了。
1 #include <cstdio> 2 using namespace std; 3 const long long int N=100000020; 4 int su[N],ans,top; 5 bool vis[N]; 6 void shai(int b) 7 { 8 for(int i=2;i<=b;i++) 9 { 10 if(!vis[i]) 11 { 12 su[top++]=i; 13 } 14 for(int j=0;j<top && i*su[j]<=b;j++) 15 { 16 vis[su[j]*i]=1; 17 if(i%su[j]==0) break; 18 } 19 } 20 return; 21 } 22 int main() 23 { 24 int n; 25 scanf ("%d",&n); 26 shai(n); 27 printf("%d",top); 28 return 0; 29 }
我以前是在放屁吗......
重新证一下为什么欧拉筛只会被最小质因子筛掉一个数。
首先枚举i,然后枚举每个p与之相乘。
如果一个数a的最小质因子是p1,a = p1 * k1
a还有一个质因子是p2,a = p2 * k2,且p1 < p2
所以p1这个质数肯定在k2中。外层枚举到k2的时候,内层枚举到p1就会break,p2不会与k2匹配来筛掉a。
然后说一下线性求逆元,如何利用之前的信息?余数!假设你要求a的逆元,s < a
然后放prime/phi/miu的模板了。
1 inline void getp(int n) { 2 phi[1] = miu[1] = 1; 3 for(int i = 2; i <= n; i++) { 4 if(!vis[i]) { 5 p[++top] = i; 6 miu[i] = -1; 7 phi[i] = i - 1; 8 } 9 for(int j = 1; j <= top && i * p[j] <= n; j++) { 10 vis[i * p[j]] = 1; 11 if(i % p[j] == 0) { 12 phi[i * p[j]] = phi[i] * p[j]; /// miu[i * p[j]] = 0 13 break; 14 } 15 miu[i * p[j]] = -miu[i]; /// get miu phi when visit 16 phi[i * p[j]] = phi[i] * (p[j] - 1); 17 } 18 } 19 return; 20 }