求1到n的质数个数和O(n)
程序员文章站
2022-03-01 17:47:14
...
我们知道:
对于一个合数 有
现在给出一个 求,所有分解出的的幂数和
例如
数字 | 个数 |
---|---|
2 | 10 |
3 | 5 |
5 | 2 |
7 | 1 |
11 | 1 |
对于一个合数 有
这是最简单的想法,先记录哪些数是质数,再把以内所有的数分解掉
int cnt;
int prime[maxn],num[maxn];//prime -> 求出来的质数 num -> 每个数出现个数
bool vis[maxn];//欧拉筛里看其是否是质数
ols(n);//这是欧拉筛
for (int i=1;i<=n;++i)
for (int j=1;j*j<=i&&j<=cnt;++j){
int t=i;
while (t%prime[j]==0) ++num[prime[j]],t/=prime[j];
}
考虑可不可以直接对整体求
这个方法对一些其他题也很有用
int cnt;
int prime[maxn],num[maxn];
bool vis[maxn];
ols(n);
for (int i=1;i<=cnt;++i){
int t=prime[i],mi=1;//mi -> mi次幂
while (t<=n){
num[prime[i]]+=n/t*mi;
t*=prime[i],++mi;
}
}
对一个数
显然是比小的,若我们知道的答案,那么的贡献就是的贡献加上对的一个贡献
但我们把的答案存下来只会增加复杂度
于是我们可以反过来循环,先对加一个贡献,之后我们就可以认为多了一个了
计算时答案就会多一,显然我们可以一直传递下去,这样每个数只用把自己最小质因子的贡献算出即可
int cnt;
int prime[maxn],num[maxn],come[maxn];//come[i] -> i的最小质因子
bool vis[maxn];
ols(n);
for (int i=n;i>=2;--i){
if (vis[i]){//如果是个合数
num[come[i]]+=num[i];//最小质因子加上当前这个数要计算次数
num[i/come[i]]+=num[i];//加上这个数需计算次数
num[i]=0;//当前这个数没了
}
}
上一篇: 求1到100之间的质数(素数)?
下一篇: 求1到n之间的质数(素数)
推荐阅读
-
c语言:求n!从1到20的和
-
C语言之函数调用01—1到n的阶乘和
-
使用C语言编写程序,计算N个整数的和(随机输入一个值,例如1到100之间所有整数的和)
-
【练习题】给定两个整数n和k,返回1 ... n中k个数的所有组合
-
1)的累加和(累乘积(阶乘))。其中n的值从键盘输入。输入一个2000年以后的年份n,输出所有介于2">
PTA判断输入的整数是否是素数,如果是则输出"1",否则输出"0." 编写程序,求自然数1至n(n>1)的累加和(累乘积(阶乘))。其中n的值从键盘输入。输入一个2000年以后的年份n,输出所有介于2
-
C#求n个数中最大值和最小值的方法
-
c语言:求1/n!从1到20的和
-
java求阶乘和1!+3!+5!+……+N!的值
-
蓝桥杯 算法训练 - 连续正整数的和 78这个数可以表示为连续正整数的和,1+2+3,18+19+20+21,25+26+27。 输入一个正整数 n(<=10000) 输出 m 行(n有m
-
妙妙屋-求小于n的所有正整数中1的个数