伪模板链接:https://www.luogu.org/problemnew/show/P3327
线筛约数个数
约数个数的定义
为了格式,写了个这玩意儿。。。
这定义应该很清楚了,写个式子吧。。。
约数个数的性质
设 x=pa11pa22...pann x = p 1 a 1 p 2 a 2 . . . p n a n
那么有个大家耳熟能详的公式:
那么 σ0(x) σ 0 ( x ) 的积性也是很显然的,博主就懒得证了。。。
这玩意儿仍然能跟数列求和扯上关系,放到后面讲。
约数个数的线筛
为了筛这玩意儿,我们还需要开另外一个数组 num[i] n u m [ i ] ,记录 i i 的最小质因数的指数,之所以记录这个,是因为线筛有一个非常好的性质:每个数只会被它的最小质因数筛去。
设,接下来考虑线筛:
1.当 T T 为质数时,显然只有两个约数, 1 1 和它自己,最小质因数也只有它自己一个,所以此时;
2.当 T T 拥有多个最小质因子(即)时,那么 T T 就比多了一个最小质因子,根据上面的公式就有 σ0(T)=σ0(i)×num[i]+2num[i]+1 σ 0 ( T ) = σ 0 ( i ) × n u m [ i ] + 2 n u m [ i ] + 1 ;
3.当 T T 的最小质因子只有一个(即)时, T T 比多了一个新的质因子,就有 σ0(T)=2σ0(i) σ 0 ( T ) = 2 σ 0 ( i ) 。
综上:
代码
void get()
{
R i,j,t;
miu[1]=d[1]=check[1]=1;
for(i=2;i<=N;++i)
{
if(!check[i])miu[i]=-1,d[i]=2,num[i]=1,p[++p[0]]=i;
for(j=1;j<=p[0];++j)
{
t=i*p[j];if(t>N)break;
check[t]=1;
if(i%p[j]==0){miu[t]=0;num[t]=num[i]+1;d[t]=d[i]/(num[i]+1)*(num[i]+2);break;}
miu[t]=-miu[i],num[t]=1,d[t]=d[i]<<1;
}
d[i]+=d[i-1],miu[i]+=miu[i-1];
}
}