2015ZZUACM暑期集训

ACM起航

这里写图片描述

8月6号—— 第一天

语法篇

代码风格


代码风格是一种规范或习惯。这就意味着并不是强制的,可以根据个人的喜好而定。

一般大型项目都有一个专门的文件规定这个项目的代码风格。最有代表性的就是linux内核的代码风格文件。

代码风格不影响程序的执行,但影响程序的可读性,可读性降低就降低了可维护性。

要养成良好的代码风格。



函数定义


每个函数的定义和说明应该从第1列开始书写。

在函数体结尾的括号(“}”)后面应该加上注释,注释中应该包括函数名,这样比较方便进行括号配对检查,也可以清晰地看出来函数是否结束


缩进

缩进要以固定的长度(一个TAB键的长度)缩进。TAB键的长度可以自己设定,通常为4或8个空格长度。

不要将多个语句放在同一行。即每行只能放一个语句。


大括号的摆放

大括号的排放全凭个人习惯。 不过推荐Kernighan和Ritchie的方式。 就是将{放在本行的结尾,}放在下一行。 用在所有不是函数的语句块(if,switch,for, while,do)。

![这里写图片描述](https://img-blog.csdn.net/20150807202947070)![这里写图片描述](https://img-blog.csdn.net/20150807203018506)

在for,if,if-else中,不论是否是单条语句,都要加上大括号。

设想本来for循环只是一个语句,而你没有写大括号。后来你发现你写错了,循环中应该有多个语句,现在再来加上大括号,有点儿麻烦了,况且很容易忘掉。


空格的摆放

在if,switch,case,for,do,while关键字的后边使用一个空格。
当声明一个指针数据或一个返回指针类型数据的函数,最好将‘*’放在紧挨数据名字或函数名字的前面。不要让‘*’紧挨类型的名字。例如:

![这里写图片描述](https://img-blog.csdn.net/20150807203322875)

在大多数二元和三元运算符的周围(每边)使用一个空格。 =  +  -  <  >  *  /  %   |  &   ^  <=   >=  ==   !=   ?  :
注意不要在结构体成员操作符‘.’和‘->’周围加上空格。
但是不要在一元运算符的后边加上空格 &   *  +   -   ~   !
不要在后缀增或减一元运算符前加上空格 ++   –
不要在前缀增或减一元运算符后加上空格 ++   –
在参数列表的逗号(, )后边加上一个空格。
在for循环中的分号后加上一个空格。

![这里写图片描述](https://img-blog.csdn.net/20150807204155183)

折行的使用

每行的长度不要超过80个字符,当程序行太长时,应该分行书写。
分行时应该按照自然的逻辑关系进行,例如:不要把一个简单的逻辑判断写在两行上。
分行后的缩进应该按照程序的逻辑关系进行对齐。例如:参数表折行后,下面的行应该在参数表左括号的下方

注释风格

C语言中使用一组(/* … */)作为注释界定符。
注释内容尽量用英语方式表述。
注释的基本样式参考范例
注释应该出现在要说明的内容之前,而不应该出现在其后。
除了说明变量的用途和语言块末尾使用的注释,尽量不使用行末的注释方式。

几种注释范例
这里写图片描述

何时需要注释

如果变量的名字不能完全说明其用途,应该使用注释加以说明。
如果为了提高性能而使某些代码变得难懂,应该使用注释加以说明。
对于一个比较长的程序段落,应该加注释予以说明。如果设计文档中有流程图,则程序中对应的位置应该加注释予以说明。
如果程序中使用了某个复杂的算法,建议注明其出处。
如果在调试中发现某段落容易出现错误,应该注明。


命名

变量的名字要见名知意。如i,j,k,tmp, ans, res, ret, num。使用大多数人都知道的缩写,否则就不要用缩写。
一般不要用大小写混合的变量名,也就是匈牙利命名法。可以使用下划线(_)来分隔两个单词。
不要只用大小写来区分两个变量。如一个叫a,一个叫A。


编译错误

Main函数必须返回int类型(正式比赛)
不要在for语句中定义类型
__int64不支持,可以用long long代替
使用了汉语的标点符号
能将整数转换为字符串而且与ANSI标准兼容的方法是使用sprintf()函数


int  num = 100;
char str[20];
sprintf(str, "%d", num);

需注意+小技巧

拷贝程序容易产生错误
算法竞赛中 不要使用头文件conio.h,包括getch(),clrscr()
提交时不要有为了锁定屏幕而有的getchar()
当输入输出很多,而且调bug需要重复输入输出时,数据的拷贝(特别是输出的提示信息)
调试的sample input的拷贝(尤其多次利用时,十分简便)




8月7号—— 第二天


字符串

——字符串注意事项

1、输入
初学者一般有个误区:如果题目包含多组测试数据,他们就会把输入的内容全部保存起来,然后再依次处理。
其实程序的输入/输出是相互独立的,因此,每当处理完一组测试数据,就应当按题目要求进行相应的输出操作。而不必将所有结果储存起来一起输出。


int main(void)
{ 
    int a, b;
    while (scanf("%d %d", &a, &b) != EOF)  
    {
        printf("%d/n", a + b);
    }
    return 0;
 }  

输出

输出
需要注意题目所强调的输出格式
这种比较简单,只要按要求来就没问题的。
比如每组输出占一行,或者每组输出后面加一个空行。
如:

字符串的读入

putchar () : 把变量中的一个字符常量输出到显示器屏幕上;
getchar ();  从键盘上输入一个字符常量,此常量就是该函数的值;
printf ();  把键盘中的各类数据,加以格式控制输出到显示器屏幕上;
scanf ();  从键盘上输入各类数据,并存放到程序变量中;
puts  ():  把数组变量中的一个字符串常量输出到显示器屏幕上;
gets  ():  从键盘上输入一个字符串常量并放到程序的数组中.
sscanf ();  从一个字符串中提取各类数据。


字符串函数的使用

scanf(“ %s%s”,str1,str2),在多个字符串之间用一个或多个空格分隔;
若使用gets函数,应为gets(str1); gets(str2); 字符串之间用回车符作分隔。
通常情况下,接受短字符用scanf函数,接受长字符用gets函数。
而getchar函数每次只接受一个字符,经常c=getchar()这样来使用。

大数、高精度运算

大数加法

分析:对于此题做法有两种:其一,使2字符串的中的字符数字减去’0’,逐个相加大于等于10的可以使本位减10,下一位自增1,后面的处理就非常简单了;其二,便是读入字符串后先让各个字符减’0’,一一对应存入整形数组中;之后再相加。对于2种方法大致是相同的,都要从后面向前加,逢十进位,以及数组初始化均要初始为0,一边方便运算。

 
for(i = 0, up = 0; i < MAX; ++i)
{
a[i] = a[i] + b[i] + up;
up = a[i] / 10;//记录进位
a[i] %= 10;
}


#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define CLR(arr, val) memset(arr, val, sizeof(arr))
#define MAX 1010
int a[MAX], b[MAX];

int main()
{
//freopen(“Input.txt”, “r”, stdin);
int N, len1, len2, i, k, up, tmp, ncase = 1;
string str1, str2;
scanf(“%d”, &N);
while(N–)
{
CLR(a, 0); CLR(b, 0);
cin>>str1>>str2;
len1 = str1.length(); len2 = str2.length();
for(i = len1 - 1, k = 0; i >= 0; –i)
a[k++] = str1[i] - ‘0’;
for(i = len2 - 1, k = 0; i >= 0; –i)
b[k++] = str2[i] - ‘0’;
for(i = 0, up = 0; i < MAX; ++i)
{
a[i] = a[i] + b[i] + up;
up = a[i] / 10;
a[i] %= 10;
}
for(i = MAX -1; i >= 0; –i)
if(a[i]) break;
printf(“Case %d:\n”, ncase++);
cout<<str1<<” + “<<str2<<” = “;
for(k = i; k >= 0; –k)
printf(“%d”, a[k]);
printf(“\n”);
}
return 0;
}


大数阶乘

0<=n<=10000 ,计算n!

拿10000的阶乘为例,最后的结果长度是35660位,所以我们定义一个40000个成员的数组就可以了。
int result[40000];
其核心思想就是把计算结果每一位上的数字保存到一个数组成员中,例如:
把124保存至数组中,保存结果应该是
result[0] 4
result[1] 2
result[2] 1
这样肯定是没有问题的,一个int型数据存放一个小于10的数是绝对不会溢出。但是处理起来就稍微有点麻烦。
把整个数组看成一个数字,这个数字和一个数相乘的时候,需要每一位都和这个乘数进行相乘运算还需要把前一为的进位加上。运算方法和小学数学是一样的,乘积的个位是当前位上应该表示的数字,10位以上的需要进位。因为乘数不可能大于10000,所以乘数和一个小于10的书相乘的时候不会大于100000,再加上前一位的进位用一个int型数据来保持这个结果就没有问题。写法如下:
int 结果 = result[x] * 乘数 + 进位;
每一位的计算结果有了,把这个结果的个位数拿出来放到这个数组元素上:
result[x] = 结果%10;
接下来的工作就是计算出进位:
进位 = 结果 / 10;

这样一位一位的把整个数组计算一遍,最后可能还有进位,用同样的方法,把进位的数值拆成单个数字,放到相应的数组元素中。
最后输出一下结果,从最高位吧数字打印一遍就OK了。

 
#include<iostream>
#include <cstdio>
#include <string.h>
using namespace std;
int b[40000];
int main()
{
int n, lena, i, j, k;
while (~scanf("%d", &n))
{
memset(b, 0, sizeof(b));
b[0] = 1;
for (i = 2; i <= n; i++)
{
for (j = 0; j < 40000; j++)
{
b[j] *= i;
}
for (j = 0; j < <40000; j++)
{
if (b[j] > 9)
{
b[j + 1] += b[j] / 10;
b[j] %= 10;
}
}
}
for (i = 40000; i>=0 && b[i] == 0; i--);
for (; i>= 0; i--)
{
printf("%d", b[i]);
}
printf("\n");
}
return 0;
}

ACM暑期集训第三天

呃。。。这一篇太多了,令写一篇。click here. Go! Go! Go!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值