7809 - 试题J:因数个数 25'(欧拉筛法求因子个数)
链接:http://oj.hzjingma.com/p/7809?view=classic
来源:竞码编程
题目描述
求所有 2 2 2 到 n n n 的整数中,因数个数第 k k k 少的数因数个数是多少。
输入描述
第一行两个正整数 n n n , k k k 即题目描述中的 n n n , k k k 。
输出描述
输出仅一行,即因数个数第 k k k 少的数因数个数。
输入
10 5
输出
3
解法一:直接暴力求解, s q r t ( n ) sqrt(n) sqrt(n) 判断因子个数。复杂度 O ( n √ n ) O(n√n) O(n√n),对于此题目来说会 T L E TLE TLE 。
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
const int maxn = 2e7 + 10;
ll cnt[maxn];
set<ll>s;ll cal(int x) {ll cnt1 = 2;if(x == 1)return 1;for(ll i = 2; i * i <= x; i++) {if(x % i == 0) {if(i * i == x)cnt1++;elsecnt1 += 2;}}return cnt1;
}int main() {int n, k;scanf("%d%d", &n, &k);for(int i = 2; i <= n; i++)cnt[i] = cal(i);sort(cnt + 1, cnt + n + 1);//for(int i=2;i<=n;i++) cout<<cnt[i]<<" "<<endl;printf("%lld\n", cnt[k + 1]);/*s.insert(cal(i));int cnt2=0;for(set<ll>::iterator it=s.begin();it!=s.end();it++) cnt[cnt2++]=*it;sort(cnt,cnt+cnt2);*/return 0;
}
解法二:用类似于埃式筛法的方法从 2 − n 2-n 2−n 此把每个数的倍数因子 + + ++ ++, s o r t sort sort 之后直接输出结果。复杂度: O ( n l o g n ) O(nlogn) O(nlogn),这个 o j oj oj 能跑过去 1 e 8 1e8 1e8 的代码。
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
const int maxn = 2e7 + 10;
int cnt[maxn];inline int read() {int x = 0, neg = 1;char op = getchar();while (!isdigit(op)) {if (op == '-')neg = -1;op = getchar();}while (isdigit(op)) {x = 10 * x + op - '0';op = getchar();}return neg * x;
}
inline void print(int x) {if (x < 0) {putchar('-');x = -x;}if (x >= 10)print(x / 10);putchar(x % 10 + '0');
}int main() {int n, k;n = read();k = read();if(n >= maxn)puts("2");else {for(int i = 2; i <= n; i++) {cnt[i] += 2;for(int j = 2 * i; j <= n; j += i)cnt[j]++;}sort(cnt + 1, cnt + n + 1);print(cnt[k + 1]);}return 0;
}
解法三:我们可以知道,对于每一个数 n n n 都可以分解成如下的式子
n = p 1 k 1 × p 2 k 2 × p 3 k 3 × ⋅ ⋅ ⋅ ⋅ × p x k x × ⋅ ⋅ ⋅ ⋅ n = p_{1}^{k_{1}} × p_{2}^{k_{2}} ×p_{3}^{k_{3}} × ···· × p_{x}^{k_{x}} × ···· n=p1k1×p2k2×p3k3×⋅⋅⋅⋅×pxkx×⋅⋅⋅⋅
p p p 表示质因子, k k k 表示质因子的个数
那个就有 n n n 的因子个数 c n t [ n ] = ( k 1 + 1 ) × ( k 2 + 1 ) × ( k 3 + 1 ) × ⋅ ⋅ ⋅ ⋅ × ( k 4 + 1 ) × ⋅ ⋅ ⋅ ⋅ cnt[n] = (k1+1) × (k2+1) × (k3+1) × ···· × (k4+1) × ···· cnt[n]=(k1+1)×(k2+1)×(k3+1)×⋅⋅⋅⋅×(k4+1)×⋅⋅⋅⋅
在欧拉筛的过程中,当 i i i 为素数的时候, c n t [ i ] = 2 cnt[i] = 2 cnt[i]=2(素数只有两个因子),此时我们在使用一个数组 t i m e s times times 来表示 i i i 的最小质因子的个数,此时 t i m e s [ i ] = 1 times[i] = 1 times[i]=1 ,这个素数当前的质因子只有 1 1 1 个。
当 i % p r i m e [ j ] = = 0 i \% prime[j] == 0 i%prime[j]==0 的时候:
i = p 1 k 1 × p 2 k 2 × p 3 k 3 i = p_{1}^{k_{1}} × p_{2}^{k_{2}} ×p_{3}^{k_{3}} i=p1k1×p2k2×p3k3
那么 i ∗ p r i m e [ j ] i * prime[j] i∗prime[j] 就是 i i i 中的最小质因子的个数加一
此时就有 t i m e s [ i ∗ p r i m e [ j ] ] = t i m e s [ i ] + 1 times[i * prime[j]] = times[i] + 1 times[i∗prime[j]]=times[i]+1 , i i i 的 最小质因子数加一就是 i ∗ p r i m e [ j ] i * prime[j] i∗prime[j] 的最小质因子的个数,此时这个数的因子个数就会随之改变,就变成了 c n t [ i ∗ p r i m e [ j ] ] = ( k 1 + 1 + 1 ) × ( k 2 + 1 ) × ( k 3 + 1 ) × ⋅ ⋅ ⋅ ⋅ × ( k 4 + 1 ) × ⋅ ⋅ ⋅ ⋅ cnt[i*prime[j]] = (k1+1+1) × (k2+1) × (k3+1) × ···· × (k4+1) × ···· cnt[i∗prime[j]]=(k1+1+1)×(k2+1)×(k3+1)×⋅⋅⋅⋅×(k4+1)×⋅⋅⋅⋅, k 1 + 1 k1+1 k1+1 是原本 i i i 的最小质因子的个数, k 1 + 1 + 1 k1+1+1 k1+1+1 则是现在这个数的最小质因子的个数,所以就可以得到 c n t [ i ∗ p r i m e [ j ] ] = c n t [ i ] / ( t i m e s [ i ] + 1 ) ∗ ( t i m e s [ i ∗ p r i m e [ j ] ] + 1 ) cnt[i*prime[j]] = cnt[i]/(times[i]+1)*(times[i*prime[j]]+1) cnt[i∗prime[j]]=cnt[i]/(times[i]+1)∗(times[i∗prime[j]]+1) 加一表示 1 1 1 也是这个数的因子,然后退出这层循环,因为后面的数会在遍历其他数字的时候被筛去。
当 i % p r i m e [ j ] ! = 0 i \% prime[j] != 0 i%prime[j]!=0 的时候:
说明 i i i 中没有这个这个素数,那么 i ∗ p r i m e [ j ] i*prime[j] i∗prime[j] 就多了一种素数,这个素数出现的次数 t i m e s [ i ∗ p r i m e [ i ] ] = 1 times[i*prime[i]] = 1 times[i∗prime[i]]=1 ,因子个数 c n t [ i ∗ p r i m e [ i ] ] = c n t [ i ] ∗ ( t i m e s [ i ∗ p r i m e [ i ] ] + 1 ) = c n t [ i ] ∗ 2 cnt[i*prime[i]] = cnt[i] * (times[i*prime[i]] + 1) = cnt[i] * 2 cnt[i∗prime[i]]=cnt[i]∗(times[i∗prime[i]]+1)=cnt[i]∗2。
复杂度: O ( n ) O(n) O(n)
#include<bits/stdc++.h>
using namespace std;const int maxn = 2e7 + 10;
int cnt[maxn] = {0, 1}, times[maxn], prime[maxn], num1[maxn]; //最小质因子出现次数
bool is_prime[maxn];inline int read() {int x = 0, neg = 1;char op = getchar();while (!isdigit(op)) {if (op == '-')neg = -1;op = getchar();}while (isdigit(op)) {x = 10 * x + op - '0';op = getchar();}return neg * x;
}
inline void print(int x) {if (x < 0) {putchar('-');x = -x;}if (x >= 10)print(x / 10);putchar(x % 10 + '0');
}void solve() {for(int i = 2; i <= maxn; i++)is_prime[i] = true;is_prime[0] = is_prime[1] = false;int num = 0;for(int i = 2; i <= maxn; i++) {if(is_prime[i]) {cnt[i] = 2;times[i] = 1;prime[num++] = i;}for(int j = 0; j < num; j++) {if(i * prime[j] > maxn)break;is_prime[i * prime[j]] = false;if(i % prime[j] == 0) { //当前素数是最小质因子times[i * prime[j]] = times[i] + 1;cnt[i * prime[j]] = cnt[i] / (times[i] + 1) * (times[i * prime[j]] + 1);break;}times[i * prime[j]] = 1;cnt[i * prime[j]] = cnt[i] * 2;}}
}int main() {solve();int n, k;n = read();k = read();if(n >= maxn)puts("2");else {//for(int i=2;i<=n;i++) cout<<cnt[i]<<" "; cout<<endl;for(int i = 2; i <= n; i++)num1[cnt[i]]++;//for(int i=2;i<=n;i++) cout<<num1[i]<<" "; cout<<endl;int cnt1 = 0;for(int i = 2; i <= n; i++) {while(num1[i]--)++cnt1;if(cnt1 >= k) {print(i);break;}}}return 0;
}
7809 - 试题J:因数个数 25'(欧拉筛法求因子个数)相关推荐
- 质数c语言欧拉筛选,Python|欧拉筛法求质数
欢迎点击「算法与编程之美」↑关注我们! 本文首发于微信公众号:"算法与编程之美",欢迎关注,及时了解更多此系列文章. 问题描述 我们知道第一个质数是 2.第二个质数是 3.第三个质 ...
- 欧拉函数求互质数个数
求解与n(1-n-1)互质的质因子的个数 解析: 定义:对于正整数n,φ(n)是小于或等于n的正整数中,与n互质的数的数目. 例如:φ(8)=4,因为1,3,5,7均和8互质. 性质:1.若p是质数, ...
- 欧拉函数求一个数倒数的循环节长度
首先,费马小定理a与p互素,则a^(p-1)≡1(mod p) 对于一个素数p,取a=10,那么10^(p-1)≡1(mod p) 如果找到一个正整数e使得10^e/p-1/p为整数,那么e就是1 ...
- python编写一个欧拉筛法求素数的小程序
n=eval(input()) #代码开始 def ouLaShai(upperBound): # 筛选器都标记为质数 filter=[True for i in range(upperBound+1 ...
- UVA10820欧拉函数求互质的对数
题意: 给出n,算出小于等于n的所有数中,有几对互质: 思路: 利用欧拉函数求与x互质的数的个数prime[x],再将prime[x]递推累加prime[x]=prime[x]+prime[x-1], ...
- 埃拉托色尼筛法和欧拉筛法
筛法 筛法的基本思想是:把从1开始的.某一范围内的正整数从小到大顺序排列, 1不是素数,首先把它筛掉.剩下的数中最小的数是素数,然后去掉它的倍数.依次类推,直到筛子为空时结束. 比如,要产生[2,n] ...
- 素数计算之埃氏筛法、欧拉筛法
埃氏筛法 int main() {const int maxNumber=200;int isPrime[maxNumber];int i;int x;for (i=0;i<maxNumber; ...
- UVA10738 Riemann vs Mertens【欧拉筛法】
One of the biggest, most mathematicians would call it THE biggest, unsolved problems in mathematics ...
- UVA12039 Goldbach‘s Cardinality【欧拉筛法】
Goldbach's cardinality (GC) of an even number means the number of ways the even number can be expres ...
最新文章
- python dataframe是什么_python – 逐个构建DataFrame的最快方法是什么?
- linux mmap 内存映射【转】
- JS Addition
- 无法删除文件提示找不到指定文件导致文件无法删除的解决方法
- VC.dll相关及其C#交互
- 面向对象 —— 结构与设计
- python正则匹配ip_python实战系列之正则获取IP地址(八)
- 大学校园无线智能调频广播系统
- 学术会议论文查重吗_投国际会议论文会查重吗
- 字符集编码(一):Unicode 之前
- Android Bluetooth HCI log 详解
- Linux - chmod授权文件权限命令详解
- Could not find artifact org.eclipse.m2e:lifecycle-mapping:pom:1.0.0
- 小米手机android目录在哪里设置字体,在哪里修改小米手机的字体大小
- 从飞信,超信看中国通讯行业的不作为
- Unity 之 ShaderGraph Channel节点解析汇总
- 2021年线上线下融合会议需求增长,Hilton EventReady Hybrid Solutions将启动
- 服务压测发现怪异现象,一顿排查,揪出“TIME_WAIT”这个内鬼~
- QDAS转换器中间XML格式说明文档
- mac苹果灯亮出风口烫开不了机解决办法