TOJ 1006 Redraiment猜想 (求素数)
2016-12-10 10:37
176 查看
题目的意思:给你一个(1~100000000)的数n,让你求1~n之间有多少个素数.
第一想法:利用下面代码求m~n之间素数,时间复杂度为nlgn,不用看就超时.
想法二:筛选加打表
#include<stdio.h>
int arr[1500];
int count = 0;
int MAX = 100000010;
bool flag[100000020];//用来判断是否为素数
void prime(int m,int n){//求m~n之间的素数
int cnt=1;
for(int i=m;i<=n;i++){
if(i ==0 || i==1){
continue;
}
cnt=1;
for(int j=2;j*j<=i;j++){
if(i%j==0){
cnt=0;
break;
}
}
if(cnt==1){
arr[count++]=i;
//System.out.println(i);
}
}
}
int main(){
int num[1001];
prime(0,10000);
for(int i=0;i<count;i++){//筛选,利用小素数筛选
int t=arr[i];
for(int j=arr[i]*arr[i];j<=MAX;j=arr[i]*t){
flag[j] = true;
t++;
}
}
flag[0] = true;
flag[1] = true;
int cnt=0;
for(int i=0;i<=MAX;i++){//打表
if(!flag[i]){
cnt++;
}
if(i%100000==0){
num[i/100000] = cnt;
}
}
int n;
while(~scanf("%d",&n) && n){
int sum=0;
sum = sum + num[n/100000];
for(int i=n/100000*100000;i<=n;i++){
if(!flag[i]){
sum++;
}
}
printf("%d\n",sum);
}
}
恩,没错还是超时!当时就想不通这得怎么过.在细看一下题目,只要求个数,想到了容斥原理.
想法三:容斥原理+筛选
容斥原理不会的去这个看看
http://www.cppblog.com/vici/archive/2011/09/05/155103.html
然后就是 :奇加偶减
#include<stdio.h>
int arr[1500];//用来存储10000以内的素数
int count=0; //记录10000以内素数的个数
void prime(int m,int n){//求素数
int cnt=1;
for(int i=m;i<=n;i++){
if(i ==0 || i==1){
continue;
}
cnt=1;
for(int j=2;j*j<=i;j++){
if(i%j==0){
cnt=0;
break;
}
}
if(cnt==1){
arr[count++]=i;
}
}
}
int main(){
prime(0,10000);
int m;
//2*3*5*7*11*13*17*19*23>100000000
while(~scanf("%d",&m) && m){
int sum = m-1;
int n=m,n1,n2,n3,n4,n5,n6,n7;
for(int i=0;i<count && arr[i]<=n;i++){
n=m;
sum = sum - (n/arr[i]-1);//在这其中包含了素数其自身
n1 = n/arr[i];
for(int j=i+1;j<count && (n1/arr[j]>0);j++){
sum = sum + n1/arr[j];
n2 = n1/arr[j];
for(int k=j+1;k<count && (n2/arr[k]>0);k++){
sum = sum -n2/arr[k];
n3 = n2/arr[k];
for(int a=k+1;a<count && n3/arr[a]>0;a++){
sum = sum + n3/arr[a];
n4 = n3/arr[a];
for(int b=a+1;b<count && n4/arr[b]>0;b++){
n5 = n4/arr[b];
sum = sum - n4/arr[b];
for(int c=b+1;c<count && n5/arr[c]>0;c++){
n6 = n5/arr[c];
sum = sum + n5/arr[c];
for(int d=c+1;d<count && n6/arr[d]>0;d++){
n7 = n6/arr[d];
sum = sum - n6/arr[d];
for(int e=d+1;e<count && n7/arr[e]>0;e++){
sum = sum + n7/arr[e];
}
}
}
}
}
}
}
}
printf("%d\n",sum);
}
return 0;
}
第一想法:利用下面代码求m~n之间素数,时间复杂度为nlgn,不用看就超时.
for(int i=m;i<=n;i++){ if(i==0 || i==1){ continue; } flag=1; for(int j=2;j*j<=i;j++){ if(i%j == 0){ flag=0; break; } } }
想法二:筛选加打表
#include<stdio.h>
int arr[1500];
int count = 0;
int MAX = 100000010;
bool flag[100000020];//用来判断是否为素数
void prime(int m,int n){//求m~n之间的素数
int cnt=1;
for(int i=m;i<=n;i++){
if(i ==0 || i==1){
continue;
}
cnt=1;
for(int j=2;j*j<=i;j++){
if(i%j==0){
cnt=0;
break;
}
}
if(cnt==1){
arr[count++]=i;
//System.out.println(i);
}
}
}
int main(){
int num[1001];
prime(0,10000);
for(int i=0;i<count;i++){//筛选,利用小素数筛选
int t=arr[i];
for(int j=arr[i]*arr[i];j<=MAX;j=arr[i]*t){
flag[j] = true;
t++;
}
}
flag[0] = true;
flag[1] = true;
int cnt=0;
for(int i=0;i<=MAX;i++){//打表
if(!flag[i]){
cnt++;
}
if(i%100000==0){
num[i/100000] = cnt;
}
}
int n;
while(~scanf("%d",&n) && n){
int sum=0;
sum = sum + num[n/100000];
for(int i=n/100000*100000;i<=n;i++){
if(!flag[i]){
sum++;
}
}
printf("%d\n",sum);
}
}
恩,没错还是超时!当时就想不通这得怎么过.在细看一下题目,只要求个数,想到了容斥原理.
想法三:容斥原理+筛选
容斥原理不会的去这个看看
http://www.cppblog.com/vici/archive/2011/09/05/155103.html
然后就是 :奇加偶减
#include<stdio.h>
int arr[1500];//用来存储10000以内的素数
int count=0; //记录10000以内素数的个数
void prime(int m,int n){//求素数
int cnt=1;
for(int i=m;i<=n;i++){
if(i ==0 || i==1){
continue;
}
cnt=1;
for(int j=2;j*j<=i;j++){
if(i%j==0){
cnt=0;
break;
}
}
if(cnt==1){
arr[count++]=i;
}
}
}
int main(){
prime(0,10000);
int m;
//2*3*5*7*11*13*17*19*23>100000000
while(~scanf("%d",&m) && m){
int sum = m-1;
int n=m,n1,n2,n3,n4,n5,n6,n7;
for(int i=0;i<count && arr[i]<=n;i++){
n=m;
sum = sum - (n/arr[i]-1);//在这其中包含了素数其自身
n1 = n/arr[i];
for(int j=i+1;j<count && (n1/arr[j]>0);j++){
sum = sum + n1/arr[j];
n2 = n1/arr[j];
for(int k=j+1;k<count && (n2/arr[k]>0);k++){
sum = sum -n2/arr[k];
n3 = n2/arr[k];
for(int a=k+1;a<count && n3/arr[a]>0;a++){
sum = sum + n3/arr[a];
n4 = n3/arr[a];
for(int b=a+1;b<count && n4/arr[b]>0;b++){
n5 = n4/arr[b];
sum = sum - n4/arr[b];
for(int c=b+1;c<count && n5/arr[c]>0;c++){
n6 = n5/arr[c];
sum = sum + n5/arr[c];
for(int d=c+1;d<count && n6/arr[d]>0;d++){
n7 = n6/arr[d];
sum = sum - n6/arr[d];
for(int e=d+1;e<count && n7/arr[e]>0;e++){
sum = sum + n7/arr[e];
}
}
}
}
}
}
}
}
printf("%d\n",sum);
}
return 0;
}
相关文章推荐
- Redraiment猜想+素数求和
- 自测题II—— 素数对猜想 (20)
- NowCoder猜想---统计n以内的素数个数
- 1007. 素数对猜想 (20)
- PAT-B 1007. 素数对猜想 (20)
- 1007. 素数对猜想 (20)(java实现)
- PAT-乙级 1007 素数对猜想
- [ACM] TOJ 1054 Jesse's Code (素数判断优化+全排列)
- AOJ-AHU-OJ-7 Redraiment猜想(优化)
- PAT 1007. 素数对猜想 (20);判断一个数为素数;java实现
- PAT练习题:素数对猜想
- PAT:1007. 素数对猜想 (20)
- PAT 1007素数对的猜想
- 哥特巴赫猜想 每个不小于6的偶数都是两个奇素数之和
- 1007. 素数对猜想 (20)
- PAT 1007. 素数对猜想
- pat 乙级 1007. 素数对猜想 (20)
- PTA-素数对猜想
- 素数对猜想
- PAT 1007. 素数对猜想