简单数据处理
筛法求素数
描述
用筛法求2——N之间的素数
输入描述
输入一个整数N,2<=N<=100000
输出描述
输出[2——N]区间内的素数
用例输入 1
20用例输出 1
2 3 5 7 11 13 17 19
把判断素数写出一个函数,方便后续直接使用
#include<stdio.h>
void prime(int n);
int main()
{
int n;
scanf("%d",&n);
prime(n);
return 0;
}
void prime(int n)
{
int x,i;
int isprime[n];//标志量,为1是素数,为0不是素数
//初识化全为素数
for(i=0;i<n;i++)
{
isprime[i]=1;
}
for(x=2;x<n;x++)
{
if(isprime[x]!=0)//x为素数
{
for(i=2;i*x<n;i++)//x的2,3,4,5倍不是素数
{
isprime[i*x]=0;
}
}
}
//输出
for(i=2;i<n;i++)
{
if(isprime[i]!=0)
{
printf("%d\t",i);
}
}
printf("\n");
}
普通方法求素数
#include<stdio.h>
#include<math.h>
int prime(int a);
int main()
{
int i,n;
scanf("%d",&n);
for(i=2;i<n;i++)
{
if(prime(i)==0)
printf("%d ",i);
}
return 0;
}
int prime(int a)
{
int i,flag=0;
for(i=2;i<=sqrt(a);i++)
{
if(a%i==0)
{
flag=1;
break;
}
}
return flag;
}
可逆素数对
如果一个数的逆序数(将其各位数字倒过来写形成的数)也是素数,则称为可逆素数,或称为可逆素数对。给定一个N,编程求解有多少对N位可逆素数对。(注:回文数不包含在内)
输入描述
一个整数N(1<N<8)
输出描述
N位整数中可逆素数对的数量
用例输入 1
2用例输出 1
4
打表的思想
问题
然后写reverse函数,开始忘记除以10了
筛法忘记是i*x了
#include<stdio.h>
#include<math.h>
void prime( );
int reverse(int n);
int isprime[9999999];
int main()
{
int i,n,count=0;
scanf("%d",&n);
//初识化全为素数
for(i=0;i<n;i++)
{
isprime[i]=0;
}
prime( );
for(i=pow(10,n-1);i<pow(10,n);i++)
{
if(isprime[i]==0&&reverse(i)>i&&isprime[reverse(i)]==0)
{
count++;
}
}
printf("%d",count);
}
void prime()
{
int i,x;
for(x=2;x<9999999;x++)
{
if(isprime[x]==0)
{
for(i=2;i*x<9999999;i++)
{
isprime[i*x]=1;
}
}
}
return ;
}
int reverse(int n)
{
int re=0;
while(n>0)
{
re=10*re+n%10;
n=n/10;
}
return re;
}
孪生素数
相差为2的两个素数称为孪生素数。编程输出给定区间内[a,b]的所有孪生素数对。
输入描述
两个整数,表示区间,1<a<b<10000;
输出描述
所有孪生素数对,每对占一行,用逗号分开;
用例输入 1
2 10用例输出 1
3,5 5,7
一开始忘记调用判断素数的函数了。。。
#include<stdio.h>
void prime();
int isprime[10000];
int main()
{
int i,a,b;
prime();
scanf("%d %d",&a,&b);
for(i=a;i<=b-2;i++)
{
if(isprime[i]==0 )
if(isprime[i+2]==0)
printf("%d,%d\n",i,i+2);
}
return 0;
}
void prime()
{
int i,x;
for(i=0;i<10000;i++)
{
isprime[i]=0;
}
for(x=2;x<10000;x++)
{
if(isprime[x]==0)
{
for(i=2;i*x<10000;i++)
{
isprime[i*x]=1;
}
}
}
}
美素数
小明对数的研究比较热爱,一谈到数,脑子里就涌现出好多数的问题,今天,小明想考考你对素数的认识。问题是这样的:一个十进制数,如果是素数,而且它的各位数字和也是素数,则称之为“美素数”,如29,本身是素数,而且2+9 = 11也是素数,所以它是美素数。
给定一个区间,你能计算出这个区间内有多少个美素数吗?输入描述
第一行输入一个正整数T,表示总共有T组数据(T <= 10000)。
接下来共T行,每行输入两个整数L,R(1<= L <= R <= 1000000),表示区间的左值和右值。输出描述
对于每组数据,先输出Case数,然后输出区间内美素数的个数(包括端点值L,R)。
每组数据占一行,具体输出格式参见样例。用例输入 1
3 1 100 2 2 3 19用例输出 1
Case #1: 14 Case #2: 1 Case #3: 4
运行超时
部分数据超时了
#include<stdio.h>
void prime();
int isprime[10000];
int sum(int n);
int main()
{
prime();
isprime[1]=1;
int i,a,b,count,n,k;
scanf("%d",&n);
for(k=1;k<=n;k++)
{
scanf("%d %d",&a,&b);
count=0;//每次都需要清零
for(i=a;i<=b-2;i++)
{
if(isprime[i]==0 &&isprime[sum(i)]==0)
count++;
}
printf("Case #%d: %d\n",k,count);
}
return 0;
}
int sum(int n)
{
int s=0;
while(n>0)
{
s=n%10+s;
n=n/10;
}
return s;
}
void prime()
{
int i,x;
for(i=0;i<10000;i++)
{
isprime[i]=0;
}
for(x=2;x<10000;x++)
{
if(isprime[x]==0)
{
for(i=2;i*x<1000;i++)
{
isprime[i*x]=1;
}
}
}
}
正确
用一个数组记录从0到i的美素数
打表
最后输出两个美素数数组的差值
#include<stdio.h>
#define max 1000000
int mss[max]={0,0,1};//从0到 i的美素数个数
int isprime[max];//为0是素数,1不是素数
void prime();//判断是否为素数
int sum(int a);//求和
void dabiao();
int main()
{
int a,b,n,i;
prime();
dabiao();
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d %d",&a,&b);
printf("%d",mss[b]-mss[a-1]);//a可能本身为美素数,所以要-1
}
}
void dabiao()
{
int i,x;
for(i=3;i<max;i=i+2)
{
if(isprime[i]==0&&isprime[sum(i)]==0)
{
mss[i]=mss[i-1]+1;
mss[i+1]=mss[i];//偶数一定不是素数
}else{
mss[i]=mss[i-1];//不是美素数就与上面的个数相等
mss[i+1]=mss[i];
}
}
}
/*可以用变量S简化步骤
void dabiao()
{
int s = 1, i;
for(i=3; i<=MAXN; i+=2) {
if(prime(i)==1 && prime(sum(i))==1)
s++;
mss[i] = s;
mss[i+1] = s;
}
}*/
int sum(int a)
{
int s=0;
while(a>0)
{
s=s+a%10;
a=a/10;
}
return s;
}
void prime()
{
int i,x;
for(i=0;i<max;i++)
{
isprime[i]=0;
}
for(x=2;x<max;x++)
{
if(isprime[x]==0)
{
for(i=2;i*x<max;i++)
{
isprime[i*x]=1;
}
}
}
return ;
}
分拆素数和
把一个偶数拆成两个不同素数的和,有几种拆法呢?
输入描述
输入包含一些正的偶数,其值不会超过10000,个数不会超过500,若遇0,则结束。
输出描述
对应每个偶数,输出其拆成不同素数的个数,每个结果占一行。
用例输入 1
30 26 0用例输出 1
3 2提示
注意:不包括两数相等的情况,例如26可分解为3+23,7+19,13+13,题意中不包含13+13
问题
问题1:又双叒叕忘记调用prime函数了
问题2:1不是素数,可以从i=2开始判断
结果就是,测试用例过了,提交上去wrong answer
然后因为输入的是偶数,可以i=3开始判断,就正确了,不解疑惑
#include<stdio.h>
int isprime[10000];
void prime();
int main()
{
prime();
int n,i,count;
scanf("%d",&n);
while(n!=0)
{
count=0;
for(i=3;i<n/2;i++)
{
if(isprime[i]==0&&isprime[n-i]==0)
{
count++;
}
}
printf("%d\n",count);
scanf("%d",&n);
}
return 0;
}
void prime()
{
int i,x;
for(i=0;i<10000;i++)
isprime[i]=0;
for(x=2;x<10000;x++)
{
if(isprime[x]==0)
{
for(i=2;i*x<10000;i++)
{
isprime[i*x]=1;
}
}
}
}
分数的四则运算
对输入的两个分数选择‘+’、‘-’、‘*’、‘/’四则运算,并以分数形式输出结果。
输入描述
第一行先输入整数T,表示总共有T组数据。
接下来共T行,每行输入分数形式的算术表达式。输出描述
最简分数形式。
用例输入 1
2 -1/2-1/3 5/6/5/6用例输出 1
-5/6 1
辗转相除法--约分
我服了,一个换行没写,一直wrong answer,硬控我三个小时
#include<stdio.h>
#include<math.h>
int yuef(int a,int b);
int main()
{
int a,b,c,d,fz,fm;
int n,k,i;
char ch;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d/%d%c%d/%d",&a,&b,&ch,&c,&d);
switch(ch)
{
case '+':
fm=b*d;
fz=a*d+b*c;
break;
case '-':
fm=b*d;
fz=a*d-b*c;
break;
case '*':
fz=a*c;
fm=b*d;
break;
case '/':
fz=a*d;
fm=b*c;
break;
}
if(fz%fm==0) printf("%d\n",fz/fm);
else
{
k=yuef(abs(fz),abs(fm));
if(fm<0)
{
fz=-fz;fm=-fm;
}
printf("%d/%d\n",fz/k,fm/k);
}
}
return 0;
}
int yuef(int a,int b)
{
int r;
while(r=a%b)
{
a=b; // 以除数作为被除数
b=r; // 以余数作为除数
}
return b; // 最后的除数为最大公约数
}
人见人爱A+B (杭电2033)
HDOJ上面已经有10来道A+B的题目了,相信这些题目曾经是大家的最爱,希望今天的这个A+B能给大家带来好运,也希望这个题目能唤起大家对ACM曾经的热爱。
这个题目的A和B不是简单的整数,而是两个时间,A和B 都是由3个整数组成,分别表示时分秒,比如,假设A为34 45 56,就表示A所表示的时间是34小时 45分钟 56秒。输入描述
输入数据有多行组成,首先是一个整数N,表示测试实例的个数,然后是N行数据,每行有6
个整数AH,AM,AS,BH,BM,BS,分别表示时间A和B所对应的时分秒。题目保证所有的数据合法。输出描述
对于每个测试实例,输出A+B,每个输出结果也是由时分秒3部分组成,同时也要满足时间的
规则(即:分和秒的取值范围在0~59),每个输出占一行,并且所有的部分都可以用32位
整数表示。用例输入 1
2 1 2 3 4 5 6 34 45 56 12 23 34用例输出 1
5 7 9 47 9 30
按照老师PPT的方法写的
#include<stdio.h>
int main()
{
int ah,am,as,bh,bm,bs;
int sum;
int n,i;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d %d %d %d %d %d",&ah,&am,&as,&bh,&bm,&bs);
sum=as+bs;
am=am+bm+sum/60;
as=sum%60;
ah=ah+bh+am/60;
am=am%60;
printf("%d %d %d\n",ah,am,as);
}
return 0;
}
逆序对
在数组中的两个数如果前面一个数大于后面的数,则这两个数组成一个逆序对。即:如果
a[i]>a[j] 且 i<j,a[i]和a[j]构成一个逆序对。例如有数组a = { 2,4,1,3,5 },
数组a的逆序对分别是:( 2,1 ),( 4,1 ),( 4,3 )。
编写代码,输入一个数组,打印出这个数组的所有逆序对。输入描述
先输入一个整数n(1<n<1000),表示数组元素的个数,接下来输入n个数组元素。
输出描述
输出数组的逆序对,每个占一行。
用例输入 1
5 2 4 1 3 5用例输出 1
(2,1) (4,1) (4,3)
思路大概就是用到了类似选择法排序的思路
#include<stdio.h>
int main()
{
int i,n,k,a[1000];
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<n-1;i++)
{
for(k=i+1;k<n;k++)
{
if(a[i]>a[k])
{
printf("(%d,%d)\n",a[i],a[k]);
}
}
}
return 0;
}
丑数
只包含质因子2,3,5的正整数被称作丑数,比如4,10,12都是丑数,而7,23,111则不是丑数,另外1也不是丑数。请编写一个函数,输入一个整数n(n<100000),能够判断该整数是否为丑数,如果是,则输出True,否则输出False。
输入描述
有多组测试数据,
对于每组数据,包含一个整数n(0<=n<100000)输出描述
判断该整数是否为丑数,如果是,则输出True,否则输出False。
用例输入 1
4 7用例输出 1
True False
#include<stdio.h>
int main()
{
int n,i,j,k;
while(scanf("%d",&n)!=EOF)
{
while(n%2==0)
{
n=n/2;
}
while(n%3==0)
{
n=n/3;
}
while(n%5==0)
{
n=n/5;
}
if(n==1) printf("True\n");
else printf("False\n");
}
return 0;
}
会绕圈的数
任意一个正整数,把它的每一位数字平方后相加得到一个数;将这个数的每一位数字再平方相加; 依次进行就会产生循环现象。设计一个程序,对给定的一个正整数m(m<10000000),打印出到出现循环为止的所有数。m=0时表示输入结束。
输入描述
对给定的一个正整数m(m<10000000),打印出到出现循环为止的所有数。m=0时表示输入结束。(每组样例包含10000组数据)
输出描述
对给定的一个正整数m(m<10000000),打印出到出现循环为止的所有数
用例输入 1
1234 0用例输出 1
1234 30 9 81 65 61 37 58 89 145 42 20 4 16 37
运行超时
#include<stdio.h>
//#define max 567
//m最大是9999999,这个数的平方和是81*7=567
int sum(int a);
int main()
{
int n,i;
int flag[9999999];
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
for(i=0;i<99999;i++)
{
flag[i]=0;
}
flag[n]=1;
printf("%d ",n);
while(1)
{
n=sum(n);
printf("%d ",n);
if(flag[n]==0)
{
flag[n]=1;
}
else
{
break;
}
}
}
return 0;
}
int sum(int a)
{
int s=0;
while(a>0)
{
s=(a%10)*(a%10)+s;
a=a/10;
}
return s;
}
虚假的RE:逆向工程
真实的RE:运行时错误