线性筛法相关

来源:互联网 发布:oa协同办公平台源码 编辑:程序博客网 时间:2024/04/28 00:12

基本证明可以看这里,懒得多写。
一个藓的证明
最关键部分
(iU)=P1P2P3...Pm1PmU(U>P1)
=UP2P3...Pm1PmP1
=i'P1(i'>i) 且i’与P1互质.

其实还可以筛其他东西
他们的本质都是要求的ix的值与最小质因子x有关系.
下面所有的分析与证明都要与线性筛法代码结合,不然读不懂.

筛出约数个数

dh写的
首先吧,肯定要维护这个玩意Ansii有多少约数
然后再维护一个Ei表示i的最小质因子的指数 (因为线筛的本质就是每个数只会被他最小的质因子筛去)
*Ansi=(a1+1)(a2+1)...(at+1) 其中ai表示第i个质因数的指数。

还有一个质数表p.
那我们来分类讨论一下。
ipj=k,

i mod pj!=0时,

pj是k的最小质因子,且这个质因子指数为1,这个由线筛的基本证明可以得到。
就说明k相对于i多了一个质因子pj
Ansk=Ansi(Epj+1)
Ek=1
其中Epj=1,因为pj是质数。

i|pj时,

pj同样是k的最小质因子,但指数不为1,这个是废话。
就说明k相对于i又多了一个质因子pj,不难推出:
Ek+=1
Ansk=Ansk/Ek(Ek+1)

于是我们就完成了这个艰巨的任务: 筛出每个数有多少约数。

void get_prime()  {      int i,j,k;      memset(flag,false,sizeof(flag));      k=0;      for(i=2;i<M;i++){          if(!flag[i]){                                              prime[k++]=i;                  e[i]=1;                  Ans[i]=2;                       //素数的约数个数为2              }              for(j=0;j<k&&i*prime[j]<M;j++){                      flag[i*prime[j]]=true;                                  if(i%prime[j]==0){                          Ans[i*prime[j]]=Ans[i]/(e[i]+1)*(e[i]+2);                          e[i*prime[j]]=e[i]+1;                          break;                      }                      else{                          Ans[i*prime[j]]=Ans[i]*Ans[prime[j]];                          e[i]=1;                      }              }          }  }  

筛出欧拉函数φ

读作φ(fai1),写作phi
φ(n)为小于等于n并与n互质的数的个数,他是积性函数 φ(a*b)=φ(a)*φ(b),gcd(a,b)=1

一个性质:
显然当x是素数时φ(x)=x1,
φ(xk)=xkxkx=xk1(x1)
因为显然只有有x这个因子的数(x的倍数)才不互质xk

现在我们来考虑一个数
由积性函数得,φ(x)=φ(p1a1)φ(p2a2)....φ(pkak)
pj为x的第j个质因子,aj为其对应的指数.
那我们之前得的那一个性质就有用了.
设x为i的第1个质因子(任意一个也可,这里方便表述),则

φ(xk)=xk1(x1)得,
φ(xk+1)=xk(x1).
φ(xk+1)=φ(xk)x

φ(xi)
=φ(xa1+1)φ(p2a2)....φ(pkak)
=xφ(xa1)φ(p2a2)....φ(pkak)
=xφ(i)

结论
x是素数,
φ(ix)=φ(i)xx|i
否则φ(ix)=φ(i)φ(x)=φ(i)(x1)由积性函数得

int prime[M/3],phi[M];  bool flag[M];  void get_prime()  {      int i,j,k;      memset(flag,false,sizeof(flag));      k=0;      for(i=2;i<M;i++){          if(!flag[i]){                                          prime[k++]=i;              phi[i]=i-1;          }          for(j=0;j<k&&i*prime[j]<M;j++){              flag[i*prime[j]]=true;                          if(i%prime[j]==0){                  phi[i*prime[j]]=phi[i]*prime[j];                      break;              }              else                  phi[i*prime[j]]=phi[i]*(prime[j]-1);          }      }  }
1 0
原创粉丝点击