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

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。
样例输入:
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);    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值