您的位置:首页 > 其它

【摘抄整理】算法竞赛入门经典(第2版)——语言篇(1-2章)

2016-07-27 10:58 399 查看
Wikipedia

C语言中文网

程序设计入门

算术表达式

#include<stdio.h>
int main()
{
printf("%d\n",1+2);
return 0;
}


#include<stdio.h>
int main()
{
printf("%.1f\n",8.0/5.0);
return 0;
}


#include<stdio.h>
#include<math.h>
int main()
{
printf("%.8f\n",1+2*sqrt(3)/(5-0.1));
return 0;
}


提示—整数值用%d输出,实数用%f输出

提示—整数/整数=整数,浮点数/浮点数=浮点数

变量及其输入

#include<stdio.h>
int main()
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",a+b);
return 0;
}


提示—scanf中的占位符和变量的数据类型应一一对应,且每个变量前加’&‘字符

圆柱体表面积

#include<stdio.h>
#include<math.h>
int main()
{
const double pi=acos(-1.0);
double r,h,s1,s2,s;
scanf("%lf%lf",&r,&h);
s1=pi*r*r;
s2=2*pi*r*h;
s=s1*2.0+s2;
printf("Area=%.3f\n",s);
return 0;
}


提示—const关键字表明值是不可改变的,用来声明常数

提示—pi=acos(-1.0)

提示—’acos‘返回的是一个数值的反余弦弧度值,其范围是 0~ pi 。 例如: acos(1) 返回值是 0

提示—’%lf‘相当于’double‘

提示—赋值是个动作,先计算右边的值,再赋给左边的变量,覆盖它原来的值

提示—printf的格式字符串中可以包含其他可打印符号,只有以’%‘开头的部分才会被后面的值替换掉,其他部分打印时原样输出

三位数反转

#include<stdio.h>
int main()
{
int m,n;
scanf("%d",&m);
n=(m%10)*100+(m/10%10)*10+(m/100);
printf("%03d\n",n);
return 0;
}


提示—’m%10‘值为m/10的余数

提示—’%03d‘一种左边补0 的等宽格式,比如数字12,%03d出来就是:012

交换变量

#include<stdio.h>
int main()
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d %d\n",b,a);
return 0;
}


#include<stdio.h>
int main()
{
int a,b,t;
scanf("%d%d",&a,&b);
t=a;
a=b;
b=t;
printf("%d %d\n",a,b);
return 0;
}


提示—赋值a=b之后,变量a原来的值被覆盖,而b的值不变

鸡兔同笼

已知鸡和兔的总数量为n,总腿数位m。

输入n和m,依次输出鸡的数目和兔的数目,如果无解,则输出No answer

#include<stdio.h>
int main()
{
int n,m,a,b;
scanf("%d%d",&n,&m);
a=(4*n-m)/2;
b=n-a;
if(m%2==1||a<0||b<0)printf("No answer\n");
else printf("%d %d\n",a,b);
return 0;
}


提示—if语句基本格式为:if(条件) 语句1;else 语句2

提示—if语句的条件是一个逻辑表达式,值可能为真,也可能为假。单个整数值也可以表示真假,其中’0‘为假,其他值为真

三整数排序

#include<stdio.h>
int main()
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a<=b&&b<=c) printf("%d %d %d\n",a,b,c);
else if(a<=c&&c<=b) printf("%d %d %d\n",a,c,b);
else if(b<=a&&a<=c) printf("%d %d %d\n",b,a,c);
else if(b<=c&&b<=a) printf("%d %d %d\n",b,c,a);
else if(c<=a&&a<=b) printf("%d %d %d\n",c,a,b);
else if(c<=b&&b<=a) printf("%d %d %d\n",c,b,a);
return 0;
}


#include<stdio.h>
int main()
{
int a,b,c,t;
scanf("%d%d%d",&a,&b,&c);
if(a>b)
{
t=a;
a=b;
b=t;
}//执行完毕后a<=b
if(a>c)
{
t=a;
a=c;
c=t;
}//执行完毕后a<=c,且a<=b
if(b>c)
{
t=b;
b=c;
c=t;
}
printf("%d %d %d\n",a,b,c);
return 0;
}


平均数(average)

输入3个整数,输出它们的平均值,保留3位小数:

#include<stdio.h>
void main()
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
double avg = (a + b + c) / 3.0;
printf("%.3lf\n",avg);
}


#include <stdio.h>
double average(int a,int b,int c);
void main()
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
double z= average(a,b,c);
printf("%.3lf\n",z);
}
double average(int a,int b,int c)
{
return (a+b+c)/3;
}


温度(temperature)

输入华氏温度f,输出对应的摄氏温度c,保留三位小数。c=5(f-32)/9

#include <stdio.h>
void main()
{
double f,c;
scanf("%lf",&f);
c=5*(f-32)/9;
printf("%.3lf\n",c);
}


连续和(sum)

输入正整数n,输出1+2+…+n的值。

#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
printf("%d\n",(n*(1+n))/2);
return 0;
}


正弦(sin)和余弦(cos)

输入正整数 n(n<360),输出n度的正弦余弦数值。

#include <stdio.h>
#include <math.h>
int main()
{
const double pi=acos(-1.0);
int n;
scanf("%d",&n);
if(n<360)
{
printf("%lf\n",sin((pi*n)/180));
printf("%lf\n",cos((pi*n)/180));
}
return 0;
}


打折(discount)

一件衣服 95元,若消费满300元,可打八五折。

输入购买衣服件数,输出需要支付的金额(单位元),保留两位小数

#include <stdio.h>
int main()
{
int n;
double m;
scanf("%d",&n);
m=n*95;
if(m>300)
{
m=m*0.85;
}
printf("%.2lf\n",m);
return 0;
}


三角形(triangle)

输入三角形 3 条边长度值(均为正整数),判断是否能为直角三角形的3个边长。

如果可以,则输出yes,不能输出no,如果无法构成三角形,则输出 not a triangle

#include <stdio.h>
int main()
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(a+b<=c||a+c<=b||b+c<=a)
{
printf("not a triangle\n");
return 0;
}
if(a*a+b*b==c*c||a*a+c*c==b*b||b*b+c*c==a*a) printf("yes\n");
else printf("no\n");
return 0;
}


年份(year)

输入年份,判断是否为润年,如果是,输出yes,否,输出no。

#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
if(n%4==0 && n%100!=0 || n%400==0) printf("yes\n");
else printf("no\n");
return 0;
}


循环结构程序设计

for循环

输出1,2,3…,n的值

#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
printf("%d\n",i);
}
return 0;
}


提示—for循环的格式为:for(初始化;条件;调整)循环体;

提示—尽量缩短变量的定义范围。例如:在for循环的初始化部分定义循环变量

aabb—7744问题

输出所有形如aabb的4位完全平方数

伪代码(pseudocode)

for(int a=1;a<=9;a++)

for(int b=1;b<=9;b++)

if(aabb是完全平方数)

printf(“%d\n”,aabb);

#include<stdio.h>
#include<math.h>
int main()
{
for(int a=1;a<=9;a++)
{
for(int b=1;b<=9;b++)
{
int n=a*1100+b*11;
int m=floor(sqrt(n)+0.5);
if(m*m==n)
{
printf("%d\n",n);
}
}
}
return 0;
}


#include<stdio.h>
int main()
{
for(int m=1;;m++)
{
int n=m*m;
if(n<1000)
continue;
if(n>9999)
break;
int a=n/100;
int b=n%100;
if(a/10==a%10 && b/10==b%10)
printf("%d\n",n);
}
return 0;
}


提示—’continue‘指直接进行下一次循环;’break‘指直接跳出循环

提示—’for(;;)‘是死循环,没有’break‘永远不会结束

while循环和do-while循环

3n+1问题

对于任意大于1的自然数n,若n为奇数,则n→3n+1,否则n→n的一半。

经过若干次这样的变换,一定会使n变为1。例如3→10→5→16→8→4→2→1

输入n,输出变换的次数。n<=10^9
fe2c


样例输入:

3

样例输出:

7

#include<stdio.h>
int main()
{
int n2,count=0;
scanf("%d",&n2);
long long n=n2; //c99
while(n>1)
{
if(n%2==1) n=n*3+1;
else n=n/2
count++;
}
printf("%d\n",count);
return 0;
}


#include<stdio.h>
int main()
{
int n,count=0;
scanf("%d",&n);
while(n>1)
{
if(n%2==1)
{
n=n*3+1;
//printf("%d\n",n);
//测试用;输入987654321时n为-1332004332,这种情况为**乘法溢出**
}
else
{
n=n/2;
//printf("%d\n",n);
}
count++;
}
printf("%d\n",count);
return 0;
}


提示—while循环的格式为:while(条件)循环体;

提示—在观察无法找出错误时,可以用“输出中间结果”的方法查错

提示—do-while循环的格式为:do{循环体}while(条件);

for(初始化;条件;调整)循环体;

||

初始化;

while(条件)

{

循环体;

调整;

}

近似计算

计算π/4 = 1- 1/3 + 1/5 - 1/7 + ….,直到最后一项小于10^-6

#include<stdio.h>
int main()
{
double sum=0;
for(int i=0;;i++)
{
double t=1.0/(i*2+1);
if(i%2==0) sum+=t;
else sum-=t;
if(t<1e-6)break;
}
printf("%.6f\n",sum);
return 0;
}


阶乘之和

输入n,计算S=1!+2!+3!+…+n!的末六位(不含前导0)。n<=10^6。

样例输入:

10

样例输出:

37913

#include<stdio.h>
int main()
{
const int MOD=1000000;
int n,S=0;
scanf("%d",&n);
if(n>25)n=25;
for(int i=1;i<=n;i++)
{
int factorial=1;//factorial阶乘
for(int j=1;j<=i;j++)
{
factorial=factorial*j%MOD;
}
S=(S+factorial)%MOD;
}
printf("%d\n",S);
return 0;
}


提示—在循环开始处定义的变量,每次执行循环体时会重新声明并初始化

提示—要计算只包含加法、减法、乘法的整数表达式除以正整数n的余数,可以在每步计算后对n取余,结果不变

循环结构程序设计中最常见的两个问题:算术运算溢出和程序效率低下

数据统计1

(书P28-P33)

输入一些整数,求出它们的最小值、最大值和平均值(保留3位小数)。

输出保证这些数都是不超过1000的整数

样例输入:

2 8 3 5 1 7 3 6

样例输出:

1 8 4.375

#include<stdio.h>
#define INF 1000000000
int main()
{
int x,n=0, min=INF,max=-INF,sum=0;
while(scanf("%d",&x)==1)
//scanf的返回值为读入的数据个数,while(scanf("%d",&n)==1)在成功读入1个数据时执行循环体。
{
sum+=x;
if(x<min)min=x;
if(x>max)max=x;
n++;
}
printf("%d %d %.3f\n",min,max,(double)sum/n);
return 0;
}


提示—在Windows下,输入完毕后先按Enter键,再按Ctrl+Z键,最后再Enter键,即可输入结束

提示—变量在未赋值之前的值是不确定的

算法竞赛入门经典 第二章 文件操作 重定向及fopen版本

数据统计2

输入一些整数,求出它们的最小值、最大值和平均值(保留3位小数)。

输出保证这些数都是不超过1000的整数。

输入包含多组数据,每组数据第一行是整数个数n,第二行是n个整数。

n=0为输入结束标记,程序应当忽略这组数据。相邻两组数据之间应输出一个空行

样例输入:

8

2 8 3 5 1 7 3 6

4

-4 6 10 0

0

样例输出:

Case1:1 8 4.375

Case2:-4 10 3.000

#include<stdio.h>
#define INF 1000000000
int main()
{
int x,n=0, min=INF,max=-INF,t=0;
while(scanf("%d",&n)==1&&n)
{
int sum=0;
for(int i=0;i<n;i++)
{
scanf("%d",&x);
sum+=x;
if(x<min)min=x;
if(x>max)max=x;
}
if(t)printf("\n");
printf("Case %d: %d %d %.3f\n",++t,min,max,(double)sum/n);
}
return 0;
}


提示—’t‘是当前编号计数器。当输出第2组或以后的结果时,会在前面加一个空行。

ACM输入输出

水仙花数(daffodil)

输出100 ~ 999中的所有水仙花数,若3位数ABC满足ABC = A^3 + B^3 + C^3,则称其为水仙花数。

例如153 = 1^3 + 5^3 + 3^3,所以153是水仙花数。

#include<stdio.h>
int main()
{
int a,b,c;
for(int i=100;i<=999;i++)
{
a=i/100;
b=i/10%10;
c=i%10;
if(i == a*a*a + b*b*b + c*c*c)
printf("%d\n",i);
}
return 0;
}


韩信点兵(hanxin)

韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次都只是掠一眼队伍的排位就知道人数了。

输入3个非负整数a,b,c,表示每种队形排尾的人数(a<3,b<5,c<7)

输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100。

样例输入:

2 1 6

2 1 4

样例输出:

Case 1:41

Case 2:No Answer

#include<stdio.h>
int main()
{
int a,b,c,n=0;
while(scanf("%d%d%d",&a,&b,&c)==3 && a>0 && b>0 && c>0 && a<3 && b<5 && c<7)
{
for(int i=10;i<=100;i++)
{
if(i%3==a && i%5==b && i%7==c)
{
printf("Case %d:%d\n",++n,i);
break;
}
}
if(i==101)
printf("Case %d:No answer\n",++n);
}
return 0;
}


倒三角形(triangle)

输入正整数n<=20,输出一个n层的倒三角形。

#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
for(int i=n;i>=1;i--)
{
for(int j=1;j<=n-i;j++)
printf(" ");
for(j=1;j<=2*i-1;j++)
printf("#");
printf("\n");
}
return 0;
}


子序列的和(subsequence)

输入两个正整数n

#include<stdio.h>
#include <math.h>
int main()
{
int m,n,j=1;
while(scanf("%d%d",&n,&m)!=EOF && n<m && m<pow(10.0,6.0))
{
double sum = 0;
if(m==0 && n==0)
return 0;
else
{
for(int i=n; i<=m; i++)
{
sum += ((1.0/i)*(1.0/i));
//分式运算把分子或分母写成浮点型,让其自动转化成小数。
}
printf("Case %d: %.5f\n",j++,sum);
}
}
return 0;
}


分数化小数(decimal)

输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b<=10^6,c<=100

输入包含多组数据,结束标记为a=b=c=0

样例输入:

1 6 4

0 0 0

样例输出:

Case 1: 0.1667

#include<stdio.h>
#include <math.h>
int main()
{
int a,b,c,j=1;
scanf("%d%d%d",&a,&b,&c);
if(a<=pow(10.0,6.0) && b<=pow(10.0,6.0) && c<=100)
printf("Case %d: %.*lf\n",j++,c,(double)a/b);
return 0;
}


提示—printf的特殊用法,对于m.n的格式可以用如下方法表示:

char ch[20];

printf(“%*.*s\n”,m,n,ch);

前边的 * 定义的是总的宽度,后边的定义的是输出的个数。分别对应外面的参数m和n 。

这种方法的好处是可以在语句之外对参数m和n赋值,从而控制输出格式。

排列(permutation)

用1,2,3,···,9 组成 3 个三位数 abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3。输出所有解。

提示:不必太动脑筋

#include <stdio.h>
void main()
{
int a,b,c,d,e,f,g,h,i;
for(a=1;a<=9;a++)
for(b=1;b<=9;b++)
for(c=1;c<=9;c++)
for(d=1;d<=9;d++)
for(e=1;e<=9;e++)
for(f=1;f<=9;f++)
for(g=1;g<=9;g++)
for(h=1;h<=9;h++)
for(i=1;i<=9;i++)
if((2*(a*100+b*10+c)==1*(d*100+e*10+f))
&&(3*(a*100+b*10+c)==1*(g*100+h*10+i))
&&(a!=b)&&(a!=c)&&(a!=d)&&(a!=e)&&(a!=f)&&(a!=g)&&(a!=h)&&(a!=i)
&&(b!=c)&&(b!=d)&&(b!=e)&&(b!=f)&&(b!=g)&&(b!=h)&&(b!=i)
&&(c!=d)&&(c!=e)&&(c!=f)&&(c!=g)&&(c!=h)&&(c!=i)
&&(d!=e)&&(d!=f)&&(d!=g)&&(d!=h)&&(d!=i)
&&(e!=f)&&(e!=g)&&(e!=h)&&(e!=i)
&&(f!=g)&&(f!=h)&&(f!=i)
&&(g!=h)&&(g!=i)
&&(h!=i))
printf("%d,%d,%d\n",a*100+b*10+c,d*100+e*10+f,g*100+h*10+i);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: