首页 > 其他 > 详细

线性筛约数个数、约数和的新方法

时间:2019-02-17 13:43:46      阅读:303      评论:0      收藏:0      [点我收藏+]

最近本人脑洞大开,发现了一种线性筛约数个数和约数和的一种神奇方法。

网上的方法我看基本都是利用num[i]数组记录i最小的质因子的个数,然后再搞搞。

我认为可以省去num[i]数组,直接进行递推。

我们知道,n的标准分解式为:

技术分享图片

那么n的约数个数及约数和分别为:

技术分享图片

对于线性筛函数f(i),只需要知道4个东西。

1:f(1) = ?

  很显然,d(1) = 1,o(1) = 1;

2:f(p) = ?,其中p为质数。

  同样很显然,d(p) = 2,o(p) = p+1;

3、4:f(i*pj) = ?,i与pj互质或不互质。

若i与pj互质,则我们可以利用积性函数的性质直接推出:

技术分享图片

最后思考当i与pj不互质的时候,考虑i,i*pj,i/pj的关系(i与pj不互质即i%pj==0)

设:

技术分享图片

则有:

技术分享图片

进行换元方便计算,设:

技术分享图片就是把pj那一项去掉

则有:

技术分享图片

将第一个式子与第二个相减,得到:

技术分享图片

那么就已经出来了,

技术分享图片

同理,约数和也可以像这样推出来。

补上代码:

int pr[N],vis[N],d[N],sigma[N],cnt;
void make(int n)
{
    d[1] = sigma[1] = 1;
    for(int i = 2;i<=n;i++)
    {
        if(!vis[i])pr[++cnt] = i,d[i] = 2,sigma[i] = i+1;
        for(int j = 1;i*pr[j]<=n&&j<=cnt;j++)
        {
            vis[i*pr[j]] = 1;
            if(i%pr[j]==0)
            {
                d[i*pr[j]] = d[i]*2-d[i/pr[j]];
                sigma[i*pr[j]] = pr[j]*(sigma[i]-sigma[i/pr[j]])+sigma[i];
                break;
            }d[i*pr[j]] = d[i]*2;
            sigma[i*pr[j]] = sigma[i]*(pr[j]+1);
        }
    }
    for(int i = 1;i<=n;i++)printf("%d %d\n",d[i],sigma[i]);
}

 

线性筛约数个数、约数和的新方法

原文:https://www.cnblogs.com/ldysy2012/p/10390857.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!