孪生素数问题 &&一种排序 && 大数阶乘 &&筛素(2)

来源:互联网 发布:linux怎么看网关 编辑:程序博客网 时间:2024/06/01 20:21

孪生素数问题

时间限制:3000 ms  |  内存限制:65535 KB
难度:2
描述
写一个程序,找出给出素数范围内的所有孪生素数的组数。一般来说,孪生素数就是指两个素数距离为2,近的不能再近的相邻素数。有些童鞋一看到题就开始写程序,不仔细看题,咱们为了遏制一下读题不认真仔细的童鞋,规定,两个素数相邻为1的也成为孪生素数。
输入
第一行给出N(0<N<100)表示测试数据组数。
接下来组测试数据给出m,表示找出m之前的所有孪生素数。
(0<m<1000000)
输出

每组测试数据输出占一行,该行为m范围内所有孪生素数组数。

样例输入
114
样例输出
4
再重新把这些题再回顾一遍:
思路:什么事孪生素数?第一要是素数,第二是连在一起的,也就是相邻的两个素数,相邻距离为1或2的素数;
所以这里就要我们会如何筛选出来素数,再找到符合条件的组合;
#include<stdio.h>int a[1000000];int main(){int i,j,sum,T,k;scanf("%d",&T);while(T--){long n;scanf("%ld",&n);for(i=2;i<=n;i++){a[i]=1;}for(i=2;i<=n;i++){if(a[i]==0)continue;     for(j=i+i;j<=n;j=i+j)     {     a[j]=0;     }     }sum=0;for(i=n;i>=2;i--){if(a[i]==1&&a[i-1]==1){sum++;}if(a[i]==1&&a[i-2]==1)  {sum++;  }}printf("%d\n",sum);}return 0; } 在for循环里面你可能会觉得为什么不能从前面往后面找符合条件的?
不是不能,而是那样会容易造成下标越界。
下面还有一种:
这个是0为素数,1为素数。
#include<stdio.h>#include<string.h>#include<time.h> #define N 1000000int a[N];int b[N];int main(){int T,n,i,j,sum;memset(a,0,sizeof(a));//clock_t star,end;//star=clock();//end=clock();//double time=(double)(end-star);//printf("%lf\n\n\n\n",time);for(i=2;i*i<=N;i++)      if(!a[i])//数组在之前初始化为0了,那么!0就是1满足条件。   {for(j=i*i;j<=N;j+=i)a[j]=1;} //这一步还是筛选素数的,就是数组a中放的都是素数。scanf("%d",&T);while(T--){sum=0;scanf("%d",&n);for(i=2,j=0;i<=n;i++)if(!a[i])//把在n范围以前的素数放进数组b里面封装好{b[j]=i;j++;}b[j]='\0';for(i=0;i<j;i++)//个人觉得应该把条件改为:i<j-1,以免下标越界!if(b[i]+1==b[i+1]||b[i]+2==b[i+1])//因为数组里面放的都是素数sum++;printf("%d\n",sum);}return 0;}

一种排序

时间限制:3000 ms  |  内存限制:65535 KB
难度:3
描述
现在有很多长方形,每一个长方形都有一个编号,这个编号可以重复;还知道这个长方形的宽和长,编号、长、宽都是整数;现在要求按照一下方式排序(默认排序规则都是从小到大);1.按照编号从小到大排序2.对于编号相等的长方形,按照长方形的长排序;3.如果编号和长都相同,按照长方形的宽排序;4.如果编号、长、宽都相同,就只保留一个长方形用于排序,删除多余的长方形;最后排好序按照指定格式显示所有的长方形;
输入
第一行有一个整数 0<n<10000,表示接下来有n组测试数据;每一组第一行有一个整数 0<m<1000,表示有m个长方形;接下来的m行,每一行有三个数 ,第一个数表示长方形的编号,第二个和第三个数值大的表示长,数值小的表示宽,相等说明这是一个正方形(数据约定长宽与编号都小于10000);
输出
顺序输出每组数据的所有符合条件的长方形的 编号 长 宽
样例输入
181 1 11 1 11 1 21 2 11 2 22 1 12 1 22 2 1
样例输出
1 1 11 2 11 2 22 1 12 2 1
#include<stdio.h>#include<stdlib.h>#define MAXN 1000struct Node {int num;int len;int wide;};int cmp(const void *c,const void *d)//通用类型 {Node *a=(Node*)c;//转化类型 Node *b=(Node*)d;if(a->num!=b->num)return a->num-b->num;else if(a->len!=b->len)return a->len-b->len;else return a->wide-b->wide;}int main(){int T,i,j,n,temp;Node s[MAXN];scanf("%d",&T);while(T--){scanf("%d",&n);for(i=0;i<n;i++){scanf("%d%d%d",&s[i].num,&s[i].len,&s[i].wide);if(s[i].len<s[i].wide){temp=s[i].len;s[i].len=s[i].wide;s[i].wide=temp;}   }printf("\n"); //sort(s,s+n,cmp);qsort(s,n,sizeof(0),cmp);for(i=0;i<n;i++){if(s[i].num==s[i+1].num&&s[i].len==s[i+1].len&&s[i].wide==s[i+1].wide) continue;printf("%d %d %d\n",s[i].num,s[i].len,s[i].wide);    }    /*for(i=1;i<m;i++)//筛掉相同的 {if(!(s[i].num==s[i-1].num && s[i].len==s[i-1].len && s[i].wid==s[i-1].wid))printf("%d %d %d\n",s[i].num,s[i].len,s[i].wid);}*/}return 0;}
这个没什么说的了就是出现这种多级排序的情况下我们如果还是一级级的分类讨论就会很让人头大。在这里就引入了两个排序函数sort 和qsort
学会怎么使用调用这些函数就会让你省很多脑细胞
也是有两个代码的:
#include<stdio.h>#include<algorithm>//这个代码的是sort排序;这是需要调用的头文件; #define MAXN 1000using namespace std;//需要的头文件 struct Node //长方形组员结构体 {int num;int len;int wide;};int cmp(Node a,Node b)//sort排序函数 {if(a.num!=b.num)return a.num<b.num;// eg:如果return x<y意思是将升序排序,return x>y。意思是降序 else if(a.len!=b.len)return a.len<b.len;//按照题意是按照升序的顺序排列 else if(a.wide!=b.wide)return a.wide<b.wide;}int main(){int T,i,j,n,temp;Node s[MAXN];scanf("%d",&T);while(T--){scanf("%d",&n);for(i=0;i<n;i++){scanf("%d%d%d",&s[i].num,&s[i].len,&s[i].wide);//输入长方形的各个组员的数据 if(s[i].len<s[i].wide)//根据题意输入较大的那个数为长,小的为宽 {temp=s[i].len;s[i].len=s[i].wide;s[i].wide=temp;}   }printf("\n"); sort(s,s+n,cmp);//调用排序函数进行排序; for(i=0;i<n;i++){if(s[i].num==s[i+1].num&&s[i].len==s[i+1].len&&s[i].wide==s[i+1].wide) continue;//这段代码是根据题意将长方形各个组员元素的数据都一样是进行删重 printf("%d %d %d\n",s[i].num,s[i].len,s[i].wide);    }}return 0;}

大数阶乘

时间限制:3000 ms  |  内存限制:65535 KB
难度:3
描述
我们都知道如何计算一个数的阶乘,可是,如果这个数很大呢,我们该如何去计算它并输出它?
输入
输入一个整数m(0<m<=5000)
输出
输出m的阶乘,并在输出结束之后输入一个换行符
样例输入
50
样例输出
30414093201713378043612608166064768844377641568960512000000000000
我们要知道一旦是大数方面的题我们就要想到数组,要用数组去解决这一类的问题!我们不是将一个有着上万位的数放在一个单元空间里面的,也不可能放的进去!而是把一个长串子的数字一个一个的单元放,连续读出就行了;
例如 我们要求一个5!
5!=1*2*3*4*5
首先把数组的第一个单元放上1:a[0]=1;
1*2=2,把2放进a[0]
2*3=6,把6放进a[0]
6*4=24,就实现把4放在a[0]里面,把2放在a[1]里面
24*5=120,实现0放在a[0],2放a[1],1放a[2];
最后把从后往前面开始走,一直遇到a[i]里面的值不为0开始读取
这就是大数放数组的思想。
#include<stdio.h>#include <string.h>#define MAX 20000//20000 的由来在下面 int main(){int T,s[MAX],n,i,j; int sum,t; scanf("%d",&T);while(T--){scanf("%d",&n);memset(s,0,sizeof(s));s[0]=1;for(i=2;i<=n;i++){t=0;for(j=0;j<MAX;j++){sum=s[j]*i+t;//计算的和 s[j]=sum%10;//每次取余数放在最低位 t=sum/10;//保存进位的数 }}    for(i=MAX-1;i>=0;i--)         if(s[i])break;//进行清零操作 for(j=i;j>=0;j--)printf("%d",s[j]);    }  printf("\n");}return 0;} 
这两个代码的不同就在时间效率的上面了,在for内循环里
for(j=0;j<MAX;j++)每次都要遍历一遍,花费了许多无用功
就是如果没有进位的后面是0,还要每次*i
并且到输出的时候还要进行清0操作;
优化:
记录下来大数的结果的非0 的位置;
那怎么记录呢?在开始求阶乘的时候数组里面的第一个数字就是1,也就是1位数了,那么每次有进位的时候并且小标下len-1的时候len++就行了,每次进位一次,就标志着结果多了一位数。
那怎么理解内层循环呢,就是你所得到的上一个数的阶乘去乘以下一个数:就是你要去求5!你现在数组里面放了4,2,0,0,0...0,记录的len=2,那么分别拿5去乘以4和2,5*4=20,取余0放在a[0],进个2,2*5+2=12取余后为2放a[1],进个1,并且这时下标已经在len-1的位置了这时候len++,len=3,再次循环一次把1放在a[2]里面,这时数组里面就是0,2,1,0,0,0...0
那么倒着数就是120了就是我们要求的结果了。
#include <stdio.h>#include <string.h>#define MAX 20000 int main(){    int a[MAX];int T,i,j;scanf("%d",&T);while(T--){int n,s,v,len=1;scanf("%d",&n);memset(a,0,sizeof(a));a[0]=1;for(i=1;i<=n;i++){v=0;for(j=0;j<len;j++){s=a[j]*i+v;a[j]=s%10;v=s/10;if(v>0 && j==len-1)len++;}}for(i=len-1;i>=0;i--)printf("%d",a[i]);printf("\n");}return 0;}
另外还有一种筛法求素的方法:
素数 #include <stdio.h>#define MAXN 100int prime[MAXN];int isNotprime[MAXN];int main(){int i,j,prime_num=0;for(i=2;i<MAXN;i++){if(isNotprime[i]==0)prime[prime_num++]=i;for(j=0;j<prime_num && prime[j]*i<MAXN;j++){isNotprime[prime[j]*i]=1;if(i%prime[j]==0)break;}}for(i=0;i<prime_num;i++)printf("%d ",prime[i]);printf("\n");return 0;}
抛开烦恼大步向前
我相信伸手就能碰到天~加油少年~
1 0
原创粉丝点击