您的位置:首页 > 其它

线性筛法相关

2016-06-01 14:54 211 查看
基本证明可以看这里,懒得多写。

一个藓的证明

最关键部分

(i∗U)=P1∗P2∗P3∗...∗Pm−1∗Pm∗U(U>P1)

=U∗P2∗P3∗...∗Pm−1∗Pm∗P1

=i'∗P1(i'>i) 且i’与P1互质.

其实还可以筛其他东西

他们的本质都是要求的i∗x的值与最小质因子x有关系.

下面所有的分析与证明都要与线性筛法代码结合,不然读不懂.

筛出约数个数

dh写的

首先吧,肯定要维护这个玩意Ansi,i有多少约数

然后再维护一个Ei表示i的最小质因子的指数 (因为线筛的本质就是每个数只会被他最小的质因子筛去)

*Ansi=(a1+1)∗(a2+1)...∗(at+1) 其中ai表示第i个质因数的指数。

还有一个质数表p.

那我们来分类讨论一下。

设i∗pj=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)=x−1,

φ(xk)=xk−xkx=xk−1(x−1)

因为显然只有有x这个因子的数(x的倍数)才不互质xk

现在我们来考虑一个数

由积性函数得,φ(x)=φ(p1a1)∗φ(p2a2)∗....∗φ(pkak)

pj为x的第j个质因子,aj为其对应的指数.

那我们之前得的那一个性质就有用了.

设x为i的第1个质因子(任意一个也可,这里方便表述),则

由φ(xk)=xk−1(x−1)得,

φ(xk+1)=xk(x−1).

即φ(xk+1)=φ(xk)∗x

φ(x∗i)

=φ(xa1+1)∗φ(p2a2)∗....∗φ(pkak)

=x∗φ(xa1)∗φ(p2a2)∗....∗φ(pkak)

=x∗φ(i)

结论

x是素数,

φ(i∗x)=φ(i)∗x,x|i

否则φ(i∗x)=φ(i)∗φ(x)=φ(i)∗(x−1),由积性函数得

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);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息