LightOJ1197【数学】
来源:互联网 发布:钱龙分析软件 编辑:程序博客网 时间:2024/05/18 05:49
引自:WONTER
题意:
给你两个数,a,b,让你求区间[a,b]里面有多少个素数;
思路:
首先要知道,我们要想筛 [1, b] 中所有的素数,只需要用到 [1, sqrt(b)] 中的所有素数来筛就可以了。
假设我们是求 [1, b] 中所有的素数,我们就只需要打表出 [1, sqrt(b)] 的素数,然后用这些素数直接去套用常规的素数筛选方法就好了,也就是(j = prime[i] * 2; j <= b; j += prime[i]) isPrime[j] = false
,但由于 b < 2^31 数据太大,我们不能直接开这么大的空间,就算能开,一个一个的置 false 也会 TLE
由于 a 和 b 的范围太大,直接素数筛肯定不可以的,但注意到 b - a <= 100000,所以可以利用这一点,减少空间的使用。所以 j 就从第一个大于 a 的 prime[i] 的倍数开始,其他的不变,并且我们置为 false 的时候也不是置isPrime[j] = false
,因为这个 j 会很大,我们把 j 离散化,置isPrime[j - a] = false
即可,最后统计 [0, b - a] 中有多少个 isPrime[j]是 true 就可以了
但要特判 a 为 1 的时候,1 也被算成素数了,这个时候要减去。
这里有一个小小的CASE就是:
求>=a的最小b倍;
①:大哥的写法:(a+b-1)/b*b;没有严格证明。。
②:队友写法:a+b-a%b,但还要判断是不是a%b!=0;
#include <bits/stdc++.h>using namespace std;typedef long long LL; const int N=1e5+10;bool isprime[N];vector<int>prime; void init(){ prime.clear(); for(int i=1;i<=55000;i++) { if(i&1) isprime[i]=true; else isprime[i]=false; } isprime[2]=1; for(int i=2;i<=55000;i++) { if(isprime[i]) { prime.push_back(i); for(int j=i+i;j<=55000;j+=i) isprime[j]=false; } }} int main(){ init(); int a,b; int T,cas=1; scanf("%d",&T); while(T--) { scanf("%d%d",&a,&b); memset(isprime,true,sizeof(isprime)); for(int i=0;i<prime.size();i++) { if(1ll*prime[i]*prime[i]>b) break; LL j; if(a/prime[i]<2) j=prime[i]+prime[i]; else j=((1ll*a-1)/prime[i]+1)*prime[i]; while(j<=b) { isprime[j-a]=false; j+=prime[i]; } } int num=b-a; int ans=0; for(int i=0;i<=num;i++) { if(isprime[i]) ans++; } if(a==1) ans--; printf("Case %d: %d\n",cas++,ans); } return 0;}
0 0
- LightOJ1197【数学】
- LightOJ1197
- LightOJ1197 Help Hanzo
- 数学
- 数学
- 数学
- 数学
- 数学
- 数学
- 数学
- 数学
- 数学
- 数学
- 数学
- 数学
- 数学
- 数学
- 数学
- Day27:Three People getting cards
- Effective Java 2.0_Item 2_中文版
- 2016*国庆
- 网络设备NAPI能力
- POJ 1470 Closest Common Ancestors(最近公共祖先)
- LightOJ1197【数学】
- 程序界面的编写--使用Xml文件进行界面的编写
- RecylerView的用法解析
- Codeforces Round #375 (Div. 2) -- E. One-Way Reform(dfs求欧拉回路)
- asa hacker
- 算法设计 -- 递归
- 浙大PTA 4-3
- Java接口中的成员变量为什么必须是public static final?
- 浙大PTA 4-2