参考博客
参考博客
参考博客

这个讲的挺好
预备知识点:
大于1的数n可以分解质因数:
n=p1a1×p2a2×p3a3*…*pka
n的约数的个数是(a1+1) * (a2+1) * (a3+1)…(ak+1)
我们先用线性筛来筛出素数

bool mark[maxn];
int prim[maxn];
int cnt;
void initial()
{cnt=0;for (int i=2 ; i<N ; ++i){if (!mark[i])prim[cnt++]=i;//存放素数for (int j=0 ; j<cnt && i*prim[j]<N ; ++j){mark[i*prim[j]]=1;//标记为素数if (!(i%prim[j]))break;}}
}

求约数个数

n的约数的个数是(a1+1) * (a2+1) * (a3+1)…(ak+1)
我们可以用线性筛筛出当前n的约数个数
证明:
d[i]表示i的约数的个数
num[i]表示i的最小素因子的个数
prim[i]表示第i个素数
分下列情况:

  1. i为质数
    因为i为质数,所以素因子只有本身,且指数为1
    所以num[i]=1,d[i]=2(1和本身)
  2. i%prim[j]!=0
    说明i不包含prim[j]这个素因子,但是i*prim[j]包含一个素因子prim[j],所以
    d(i∗prime[j])=(1+r1)∗……∗(1+rk)∗(1+1)=d[i] * d[prim[j]] = d[i] * 2
    而且因为我们是从小到大枚举,所以当前的prim[j]必然是i * prim[j]的最小素因子,所以num[i * prim[j]] = 1
  3. i%prim[j]= =0
    i中包含prim[j],且为i的最小素因子
    d(i∗prime[j])=(1+r1+1)∗……∗(1+rk)
    d(i∗prime[j])=d(i)/(num(i)+1)∗(num(i)+2)
    num(i∗prime[j])=num(i)+1
#include <iostream>
#include <cstdio>
#include <cstring>using namespace std;const int wx=1017;int isprime[wx],prime[wx],d[wx],num[wx];
int tot,n,m;inline int read(){int sum=0,f=1; char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}return sum*f;
}void Euler(){memset(isprime,1,sizeof isprime); d[1]=1;for(int i=2;i<=n;i++){if(isprime[i]){prime[++tot]=i;d[i]=2;num[i]=1;}for(int j=1;j<=tot&&i*prime[j]<=n;j++){isprime[i*prime[j]]=0;if(i%prime[j]==0){d[i*prime[j]]=d[i]/(num[i]+1)*(num[i]+2);num[i*prime[j]]=num[i]+1; break;}else{d[i*prime[j]]=d[i]*2;num[i*prime[j]]=1;}}}
}int main(){n=read(); Euler();for(int i=1;i<=n;i++)printf("%d %d\n",i,d[i]);return 0;
}

线性筛约数和

我们用sd(i)表示i的约数和
根据算数基本定理:
sd(n)=(1+p1+p21+……+pr11)∗(1+p2+p22+……+pr22)∗……∗(1+pk+p2k+……+prkk)
最小质因子的那一项是(1+p1+p21+……+pr11)
我们用num[i]来表示最小质因子的那一项
证明:
和上面一样分类讨论:

  1. i为素数
    sd(i)=i+1num(i)=i+1
  2. i%prim[j] ! = 0
    i∗prime[j]里原先没有prime[j]这一项,加上后:
    sd(i∗prime[j])=sd(i)∗sd(prime[j])
    num(i∗prime[j])=1+prime[j]
    (大体思路如上)
  3. i%prim[j] = =0
    d(i∗prime[j])=(d(i)/num(i)∗(num(i)∗prime[j])+1
    num(i∗prime[j])=num(i)∗prime[j]+1

代码:

#include <iostream>
#include <cstdio>
#include <cstring>using namespace std;const int wx=1017; inline int read(){int sum=0,f=1; char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}return sum*f;
}int isprime[wx],sd[wx],num[wx],prime[wx];
int n,tot;void Euler(){memset(isprime,1,sizeof isprime); sd[1]=1;for(int i=2;i<=n;i++){if(isprime[i]){prime[++tot]=i;sd[i]=1+i; num[i]=1+i;}for(int j=1;j<=tot&&prime[j]*i<=n;j++){isprime[i*prime[j]]=0;if(i%prime[j]!=0){sd[i*prime[j]]=sd[i]*sd[prime[j]];num[i*prime[j]]=prime[j]+1;}else{sd[i*prime[j]]=sd[i]/num[i]*(num[i]*prime[j]+1);num[i*prime[j]]=num[i]*prime[j]+1; break;}}}
}int main(){n=read(); Euler();for(int i=1;i<=n;i++)printf("%d %d\n",i,sd[i]);return 0;
}

[数论]线性筛——约数个数与约数和相关推荐

  1. 算法刷题-数论-试除法求约数、约数个数、约数之和、最大公约数(辗转相除法)

    文章目录 acwing869. 试除法求约数 acwing870. 约数个数 acwing871. 约数之和 acwing872. 最大公约数 acwing869. 试除法求约数 acwing869. ...

  2. 数论 - 约数基础 【 试除法求所有约数 + 约数个数和约数之和 + 欧几里得算法-求解最大公约数 】

    数论-约数基础 1.约数定义 约数,又称因数.整数a除以整数b(b≠0) 除得的商正好是整数而没有余数,我们就说a能被b整除,或b能整除a.a称为b的倍数,b称为a的约数.在大学之前,"约数 ...

  3. 约数个数、约数之和、约数

    文章目录 试除法求一个数的所有约数 求约数个数 求约数之和 欧几里得算法 试除法求一个数的所有约数 vector<int> get_divisors(int n) //求n的约数 {vec ...

  4. 数论(三)——约数(约数个数,约数和,公约数)

    目录 试除法求约数 求约数个数 约数之和 欧几里得算法 试除法求约数 试除法求一个数的所有约数,思路与判断质数的思路一样,优化的方法也是一样的,这里就不再赘述,没有看过我之前关于质数的博客可以点这里. ...

  5. 约数个数定理约数和定理

    1.如果我们要求一个数的所有因数的个数会怎么去求呢? 首先想到最简单的方法就是暴力求解就可以.当然数据小.或者测试数据少就很简单就可以过了. 2.如果求一个区间内的数的所有因数的个数呢?或者求一个区间 ...

  6. 【算法基础15】如何求约数?约数个数?约数之和?最大公约数?

    一.试除法求约数 主要思想:由于当n/a=b时,a和b都是n的约数,即约数总是成对出现,可以在一次循环中同时找到i和n/i两个约数,只需要循环n/i次就能找到所有约数. 例题:求一个数的所有约数,并将 ...

  7. Bzoj 2749: [HAOI2012]外星人 欧拉函数,数论,线性筛

    2749: [HAOI2012]外星人 Time Limit: 3 Sec  Memory Limit: 128 MB Submit: 568  Solved: 302 [Submit][Status ...

  8. 线性筛——约数的个数

    如果不会线性筛素数的话,建议先看这篇博客了解一下线性筛素数. 线性寻找约数的个数(积性函数都可以线性筛)主要是在线性筛素数的基础上得到的 用 f ( n ) f(n) f(n) 表示 n n n 的约 ...

  9. 【线性筛】【质因数分解】【约数个数定理】hdu6069 Counting Divisors

    d(x)表示x的约数个数,让你求(l,r<=10^12,r-l<=10^6,k<=10^7) #include<cstdio> using namespace std; ...

最新文章

  1. 末学者笔记--openstack共享组件:rabbitmq(3)
  2. j2ee mysql 图片_实战 J2EE 开发购物网站 二_MySQL
  3. PyTorch 实现经典模型8:FCN
  4. 你是一直认为 count(1) 比 count(*) 效率高么?
  5. 很多人都不知道学了c/c++到底能做什么?让大牛来告诉你............
  6. tomcat8 安装|解决启动慢|进入管理|host-manager 403错误
  7. 构建Spring微服务并对其进行Dockerize生产
  8. linux运行core控制台程序,VisualStudioCode创建的asp.net core控制台程序部署到linux
  9. linux的常用操作——压缩和解压缩
  10. 浅入浅出 Android 安全:第四章 Android 框架层安全
  11. Spring Boot中的事务管理与手把手实战
  12. 阿里云系统盘扩容及数据盘分区、格式化分区、挂载、取消挂载
  13. specification jpa 复杂查询
  14. 如何通过织云Lite愉快地玩转TSW
  15. Wangle源码分析:Service
  16. android 动画直播,直播动画实现方案一
  17. 实际我的暗影精灵4设置U盘启动的方法
  18. 深度学习公开语音识别数据集下载 | 论文下载|音频数据集|corpus ——简记
  19. 我爱Java系列之---【组员在idea中使用Git】
  20. 数据结构约瑟夫环实验报告

热门文章

  1. 男科医生到底有多不正经… | 今日最佳
  2. 好强大的仿生机械,这才是真正的黑科技!
  3. c语言中把每个字母向前移1位,C语言:将字符串中的前导*号全部移到字符串的尾部。...
  4. java连接mysql数据库连接池_java使用原生MySQL实现数据的增删改查以及数据库连接池技术...
  5. php sorcket_PHP: Sockets - Manual
  6. mysql 精度_mysql-笔记 精度
  7. react 版权问题_react使用fetch封装请求的方法-简单易懂
  8. bcm943602cs蓝牙用不了_原来手机的蓝牙功能这么强大!除了连接耳机,还有这六大实用功能...
  9. 剑指offer-数组中的重复的数字-p39
  10. [JavaWeb-CSS]CSS概述