HDU 5750 快速筛素数法打表
来源:互联网 发布:剑三明教成女捏脸数据 编辑:程序博客网 时间:2024/05/29 15:24
题目大意:x能整除n,x就是n的positive proper divisor,但n本身不算,给你两个数n和d,找出所有小于n的数中,最大positive proper divisor是d个数,T组测试数据。
解题思路:很明显对于每个数x,找出其最小素因数m,如果x/m等于d,那么x的最大positive proper divisor就是d,如果这样枚举小于n的每一个数,总共需要 T n √n的时间。
还有更优的做法,我们可以直接素数筛筛出所有的素数,另每个素数x乘d,一定满足x<=d&&x*d<n。
分两种情况,第一种情况是d是素数,我们只要枚举素数x就好,如果x小于等于d且x×d小于n就让ans++,否则终止循环。
第二种情况是d不是素数,我们假设d=5×7×11,很明显当
x=2,x*d=2 ×5×7×11 或者x=3,x*d=3×5×7×11 或 x*d= 5 ×5×7×11都可以 ,x*d的最大positive proper divisor都是d
,如果x=7,x*d= 7×5×7×11的话,最大positive proper divisor是7×7×11,不为d就不满足条件,所以我们可知,我们枚举的素数小于等于d的最小素数就好了。操作跟一种情况一样,加上一句如果d%x==0且x!=d,break,就好了,这种说明d不是素数,小于d的素数已经被计算过。
另附两种素数打表代码,一个快一个慢
快速素数打表:
//prime[]存储了小于n的素数,下标从1开始//visit[]数组标记了是否为素数,bool类型//返回值num表示小于n的素数的个数ll prime[maxn];bool visit[maxn];ll init_prim(ll n){ memset(visit, true, sizeof(visit)); ll num = 0; for (ll i = 2; i <= n; ++i) { if (visit[i] == true) { num++; prime[num] = i; } for (ll j = 1; ((j <= num) && (i * prime[j] <= n)); ++j) { visit[i * prime[j]] = false; if (i % prime[j] == 0) break; //点睛之笔 } } return num;//返回质数个数}
比较慢的一种素数打表
int maxn=100000;int vis[maxn];ll init_prim(ll n){ ll num=0; memset(vis,0,sizeof(vis)); for(ll i=2; i<=n; i++) { if(!vis[i]) { num++; for(ll j=i*i; j<=n; j+=i) { vis[j]=1; } } }}
题目AC代码:
#include <iostream>#include <stdio.h>#include <cmath>#include <algorithm>#include <cstring>#include <map>#include <queue>#include <stack>#include <vector>using namespace std;#define inf 0x3f3f3f3f#define uLL unsigned long long#define maxn 100010typedef long long ll;typedef long long LL;//prime[]存储了小于n的素数,下标从1开始//visit[]数组标记了是否为素数,bool类型//返回值num表示小于n的素数的个数ll prime[maxn];bool visit[maxn];ll init_prim(ll n){ memset(visit, true, sizeof(visit)); ll num = 0; for (ll i = 2; i <= n; ++i) { if (visit[i] == true) { num++; prime[num] = i; } for (ll j = 1; ((j <= num) && (i * prime[j] <= n)); ++j) { visit[i * prime[j]] = false; if (i % prime[j] == 0) break; //点睛之笔 } } return num;//返回质数个数}int main(){ int T; ll n,d; ll cnt; init_prim(maxn); cnt=init_prim(maxn); scanf("%d",&T); while(T--) { ll ans=0; scanf("%I64d%I64d",&n,&d); for(int i=1;i<=cnt;i++) { ll x=prime[i]; if(x<=d&&x*d<n) ans++;//满足条件ans++ if(x>d||x*d>=n) break;//当枚举的值超出x的范围时结束循环 if(d!=x&&d%x==0) break;//当枚举的素数为d的因数时结束循环(当前值被统计到结果中) } printf("%I64d\n",ans); } return 0;}
0 0
- HDU 5750 快速筛素数法打表
- 快速素数筛模板
- 快速幂+素数 HDU 1905 Pseudoprime numbers
- HDU 1905 Pseudoprime numbers【素数】【快速幂】
- 【hdu】 Pseudoprime numbers 伪素数(快速幂+判定素数)
- 素数筛实现素数的快速筛选
- Hdu 5750 Dertouzos 素数筛 解题报告
- HDU 5750 Dertouzos(素数)
- HDU 筛素数
- UVA10006->素数筛&&快速幂取模
- 快速求素数筛法
- 快速幂和素数筛
- 筛法快速求解素数
- 快速幂 & 素数筛法
- [数论] HDU 1431 素数回文 筛素数
- HDU 4548 美素数 // 素数筛法
- hdu 4715 Difference Between Primes【筛法快速求素数表+思维】
- hdu 1262 寻找素数对(素数的判断,快速筛选素数)
- JNI(Java Native Interface)首次使用
- LLDB之基本命令使用(Swift)
- JavaWeb的Filter过滤器应用
- Cpp环境【POJ3069】【Vijos2995】 萨鲁曼的大军 Saruman's Army
- nncq---原来写人才网的档案查询页面
- HDU 5750 快速筛素数法打表
- Java基础:逻辑与或和按位与或的区别
- 第一次机房收费系统--安装连接之初体验
- #pragma预编译的使用
- 好模板收藏地址
- Spring Aop实例(XML形式)
- PHP中session的工作原理
- <30天自制操作系统>第六天
- Android博客周刊第28期