线性筛
线性筛素数
#define MAXN 1000000
int prim[MAXN],vis[MAXN],c;
void Solve()
{
mu[1]=1;
for(int i=2;i<MAXN;i++)
{
if(!vis[i])
prim[c++]=i;
for(int j=0;1LL*prim[j]*i<MAXN;j++)
{
vis[i*prim[j]]=1;
if(i%prim[j]==0)
break;
}
}
}
一些理解:
1.一个合数
被筛出来时,
;
2.当满足 if (
%
) break 时,合数
还没有被筛出来。
当
,内层循环枚举到
时,才会被筛出。
积性函数
欧拉函数
即小于等于x并且和x互质的数的个数
性质
1:(积性函数)
,其中gcd(a,b)=1;
2:
3:小于
且与
互质的数的和:
证明:显然,若
与
互质,则
与
互质(由辗转相除法可知)
当
时,
为偶数,也就是说
与
成对出现,有
对,此时
当
时,该式成立。
线性筛欧拉函数
int phi[MAXN],prim[MAXN],c;
void Solve()
{
phi[1]=1;
for(int i=2;i<MAXN;i++)
{
if(!phi[i])
{
prim[c++]=i;
phi[i]=i-1;
}
for(int j=0;1LL*prim[j]*i<MAXN;j++)
{
if(i%prim[j]==0)
{
phi[i*prim[j]]=prim[j]*phi[i];
break;
}
phi[i*prim[j]]=(prim[j]-1)*phi[i];
}
}
}
补充:当我们只需要求某一个数的 ,可用以下筛法
要预处理出
以内素数。
时间复杂度:O(
)
LL Solve(LL n)
{
LL ret=n;
for(int i=0;i<tot&&prim[i]<=n;i++)
if(n%prim[i]==0)
{
ret=ret/prim[i]*(prim[i]-1);
while(n%prim[i]==0) n/=prim[i];
}
if(n!=0) ret=ret/n*(n-1);
return ret;
}
莫比乌斯函数
(1)=1
(d)=
,
,其中 p 为素数
(d)=0,其他
性质
1:(积性函数)
,其中gcd(a,b)=1;
2:
3:
线性筛莫比乌斯函数
#define MAXN 1000000
int mu[MAXN],prim[MAXN],vis[MAXN],c;
void Solve()
{
mu[1]=1;
for(int i=2;i<MAXN;i++)
{
if(vis[i]==0)
{
prim[c++]=i;
mu[i]=-1;
}
for(int j=0;1LL*prim[j]*i<MAXN;j++)
{
vis[i*prim[j]]=1;
if(i%prim[j]==0)
{
mu[i*prim[j]]=0;
break;
}
mu[i*prim[j]]=-mu[i];
}
}
}
莫比乌斯反演
形式一:
形式二:
一些问题 bzoj 3930 选数
1.求
令
,
逆元函数
模数为m:
性质
1.(完全积性函数,不需要(a,b)=1)在模素数p的意义下:
证明
在模素数p的意义下:
线性筛逆元函数
Solution1:(P为素数)
int inv[MAXN],prim[MAXN],c,P;
void Solve()
{
inv[1]=1;
for(int i=2;i<MAXN;i++)
{
if(inv[i]==0)
{
prim[c++]=i;
inv[i]=PowMod(i,P-2);
}
for(int j=0;1LL*prim[j]*i<MAXN;j++)
{
inv[i*prim[j]]=inv[i]*inv[prim[j]];
if(i%prim[j]==0)
break;
}
}
}
Solution2:(P为素数)
void Solve()
{
inv[1]=1;
for(int i=2;i<P;i++)
inv[i]=1LL*(P-P/i)*inv[P%i]%P;
}
证明:
假设当前已经求出
,当前要求
.
P%k;
令 a=P%k ,有
;
又
补充:求阶乘的逆元
void Solve()
{
fac[0]=1;
for(int i=1;i<=n;i++)
fac[i]=1LL*fac[i-1]*i%P;
inv[n]=PowMod(fac[n],P-2);
for(int i=n-1;i>=0;i--)
inv[i]=1LL*(i+1)*inv[i+1]%P;
}
线性筛 为定值
令 ,其中,
int g[MAXN],ek[MAXN],prim[MAXN],c,P,b;
void Solve()
{
g[1]=1;
for(int i=2;i<MAXN;i++)
{
if(g[i]==0)
{
prim[c++]=i;
g[i]=max((b%i==0)*i,1);
ek[i]=i;
}
for(int j=0;1LL*prim[j]*i<MAXN;j++)
{
if(i%prim[j]==0)
{
ek[i*prim[j]]=ek[i]*ek[prim[j]];
if(b%(ek[i]*prim[j])==0) g[i*prim[j]]=g[i]*prim[j];
else g[i*prim[j]]=g[i];
break;
}
ek[i*prim[j]]=prim[j];
g[i*prim[j]]=g[i]*g[prim[j]];
}
}
}
的正因子数目
记
性质
1.(积性函数)
,其中
线性筛
int d[MAXN],e[MAXN],prim[MAXN],c;
void Solve()
{
g[1]=1;
for(int i=2;i<MAXN;i++)
{
if(d[i]==0)
{
prim[c++]=i;
d[i]=2;
e[i]=1;
}
for(int j=0;1LL*prim[j]*i<MAXN;j++)
{
if(i%prim[j]==0)
{
d[i*prim[j]]=d[i]/(e[i]+1)*(e[i]+2);
e[i*prim[j]]=e[i]+1;
break;
}
d[i*prim[j]]=d[i]*d[prim[j]];
e[i*prim[j]]=1;
}
}
}
的正因子之和
性质
1.(积性函数)
,其中
线性筛
Solution1:
令
,当
是
的最小质因子时:
记
则
LL s[MAXN],pe[MAXN];
int prim[MAXN],c;
void Solve()
{
s[1]=1;
for(int i=2;i<MAXN;i++)
{
if(!s[i])
{
prim[c++]=i;
s[i]=i+1;
pe[i]=i*i;
}
for(int j=0;1LL*prim[j]*i<MAXN;j++)
{
if(i%prim[j]==0)
{
pe[i*prim[j]]=pe[i]*prim[j];
s[i*prim[j]]=s[i]/(pe[i]-1)*(pe[i*prim[j]]-1)
break;
}
s[i*prim[j]]=s[i]*s[prim[j]];
pe[i*prim[j]]=pe[prim[j]];
}
}
}
Solution 2:
令
,当
是
的最小质因子时:
LL s[MAXN];
int prim[MAXN],c;
void Solve()
{
s[1]=1;
for(int i=2;i<MAXN;i++)
{
if(s[i]==0)
{
prim[c++]=i;
s[i]=i+1;
}
for(int j=0;1LL*prim[j]*i<MAXN;j++)
{
if(i%prim[j]==0)
{
s[i*prim[j]]=s[i]*(prim[j]+1)-s[i/prim[j]]*prim[j];
break;
}
s[i*prim[j]]=s[i]*s[prim[j]];
}
}
}
补充题目
模板题
CQOI 3512 筛法求素数表
CQOI 3515 乘法逆元表
CQOI 2710 欧拉函数的值
POJ 2478 Farey Sequence
51Nod 1240 莫比乌斯函数
模板变式
HDU 3501 Calculation:利用欧拉函数性质3
POJ 3090 Visible Lattice Points
HDU 5317 RGCDQ