入门基础常识

一、输入输出

1、scanf()函数的返回值---输入变量的数量

EOF,这是在stdio.h里面定义的常量(通常值为-1),表示输入流已经结束。在Windows下,用户按下CTRL+Z(会看到一个^Z字符)再按下回车(可能需要重复2次),就表示输入结束;Linux/Unix下使用CTRL+D表示输入结束。

字符:c=getchar(),cin.getline(),getline();

2、64bit整数问题

在g/g++上是用long long来定义,由于ZJU上的是g/g++,so可以用long long型。但是对于一些VC就要用_int64,因此有时需要注意操作系统和编译器。

例:hdu2132 其中的 和sum均为long long 型

至于为啥 i 也得为long long (= =) 私心认为和计算表达式在计算机中的底层实现有关,如 i * i *i 这样的中间值是存在变量 i 里的所以 i 也得为 long long型。(以后证实弄懂来补)

#include <stdio.h>

long long sum[100002]={0};
int main()
{
    long long i; //特别注意i为long long型 
    int n;
    for(i=1;i<=100002;i++)
    {
        if(i%3==0)
            sum[i]=sum[i-1]+i*i*i;
        else
            sum[i]=sum[i-1]+i;
    }
    while(scanf("%d",&n)!=EOF&&n>=0 )
    {
        printf("%I64d\n",sum[n]);
    }
    return 0;
}

 

3、大数组RE(Runtime Error)问题

在C/C++中, 对于在函数内定义的变量(包括main()函数), 都是在程序的栈空间内分配的(这个空间相对有限)。如果定义一个内存使用量达到MB级别的数组,一般就会StackOverf low,RE了。所以遇到大数组的时候建议大家都定义成全局变量。这样就可以在编译的时候就为它们分配好足够的空间。

4、精度问题

对于f loat/double的比较,通常可能会有舍入误差(比如0.1这个东西在IEEE754标准下永远不可能精确存储)导致本来应该相等的不相等,所以建议这样:先定义一个常量,比如精度在10^-9这个额度(要根据具体问题判断这个额度!)

#define EPS (1e-9)
然后用这样一个比较函数:

int cmpDouble(double a, double b){
if(fabs(a - b) < EPS) return 0; // a == b
else
if(a - b > 0) return 1; // a > b`
else return -1; // a < b
}

对于f loat/double的取整也很有技巧:f loor和ceil不一定能给你你想要的结果(why?)对于一个double类型的a,想想这些表达式的意义:(提示:取(?)整,四舍五入)
(int)(a + EPS)
(int)(a + EPS + 0.5)
以上对于正数成立,对于负数呢?

二、字符串

1、基本操作

1. 初始化: memset函数
2. 获取长度: strlen函数
3. 复制字符串: strcpy函数
4. 连接字符串:strcat函数,当然C++可以直接用“+”就可以
5. 比较字符串:strcmp函数

2、基本算法:BF算法,KMP算法

例:ZOJ 1050、1315、1151、1174   hdu 4148

 

三、基础算法

1、递归与分治

  1、程序调用自身的编程技巧称为递归。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂问题层层转化为一个与原问题相似的规模较小的问题来求解。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进,当边界条件满足时,递归返回。

  2、构成递归需具备的条件:1、子问题需与原始问题为同样的事,且更为简单;

             2、不能无限制的调用本身,须有个出口,化简为非递归状况处理。

  3、递归的优缺点:(优)结构清晰,可读性强,容易用数学归纳法来证明算法的正确性。(缺)耗时,占内存使运行效率低。

  4、典例:斐波那契数列,汉诺塔问题。

void Hannoi(int n,int from,int temp,int to)
{
    if(n==1)
        move(n,from,to);
    else
    {
        Hannoi(n-1,from,temp);
        move(n,from,to);
        Hannoi(n-1,temp,to);
    }
 } 

   5、数学归纳法是数学中重要的一种证明方法。当证明一个数学定理时,采用数学归纳法的思路是,先证明对于简单的可以代入的数,定理成立;再在假设定理对某一数N成立的前提下,证明 N + 1 也是成立的。其实,数学归纳法利用的是递推的原理,形象的可以叫做多米诺原理。因为 N + 1 的成立就可以向前向后递推所有数都成立。

  6、设计递归程序的步骤:

    1、用数学归纳法分析问题,根据数学归纳法的第一步,得出截止部分。

    2、根据数学归纳法的第三步来构造函数的递归部分。就是找出R(N)和R(N-1)的关系式。

  7、分治:将问题分解为较小规模的模式,分而治之,其过程自然产生了递归。

2、递推

某些问题中相邻两项或多项存在某种关系或规律即可归纳为递推关系式。已知初值通过递推式求结果为顺退法,已知结果求初值为逆推法,递推不用进出栈,所以效率比递推高。

3、枚举

即穷举,暴力求解。

一直没遇到枚举有优势的题,这题topcoder的C很好,一道蛮好的枚举题 https://abc088.contest.atcoder.jp/tasks/abc088_c

C - Takahashi's Information


Time limit : 2sec / Memory limit : 256MB

Score: 300 points

Problem Statement

We have a 3×3 grid. A number ci,j is written in the square (i,j), where (i,j) denotes the square at the i-th row from the top and the j-th column from the left.
According to Takahashi, there are six integers a1,a2,a3,b1,b2,b3 whose values are fixed, and the number written in the square (i,j) is equal to ai+bj.
Determine if he is correct.

Constraints

  • ci,j (1≤i≤3,1≤j≤3) is an integer between 0 and 100 (inclusive).

Input

Input is given from Standard Input in the following format:

c1,1 c1,2 c1,3
c2,1 c2,2 c2,3
c3,1 c3,2 c3,3

Output

If Takahashi's statement is correct, print Yes; otherwise, print No.


Sample Input 1

Copy
1 0 1
2 1 2
1 0 1

Sample Output 1

Copy
Yes

Takahashi is correct, since there are possible sets of integers such as: a1=0,a2=1,a3=0,b1=1,b2=0,b3=1.


Sample Input 2

Copy
2 2 2
2 1 2
2 2 2

Sample Output 2

Copy
No

Takahashi is incorrect in this case.


Sample Input 3

Copy
0 8 8
0 8 8
0 8 8

Sample Output 3

Copy
Yes

Sample Input 4

Copy
1 8 6
2 9 7
0 7 7

Sample Output 4

Copy
No

#include <iostream>

using namespace std;

int main()
{
    int c[3][3]={0},a[3]={0},b[3]={0},flag=1;
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
            cin >> c[i][j];
    for(int i=0;i<=100;i++)     //枚举
    {
        a[0]=i;
        b[0]=c[0][0]-i;
        b[1]=c[0][1]-i;
        b[2]=c[0][2]-i;
        a[1]=c[1][0]-b[0];
        a[2]=c[2][0]-b[0];
        for(int j=0;j<3;j++)    //验证
        {
            for(int k=0;k<3;k++)
            {
                if(a[j]+b[k]!=c[j][k])
                {
                    flag=0;
                    continue;
                }
            }
        }
        if(flag==1)
        {
            cout << "Yes" << endl;
            return 0;
        }
        flag=1;
    }
    cout << "No" << endl;   //枚举完了,未找到合适解;
    return 0;
}

 

4、贪心

求解问题时只考虑局部最优解,而局部最优解的最终应用结果就是全局最优解。例:hdu2037  hdu1052

5、模拟

用最基本的方式思考问题。

6、构造

当问题有一个或多个解时, 我们找到了直接生成其中一个解的办法,或者从一个解生成多个解的办法时,直接通过构造生成解,从而避免去搜索穷举产生解。

 

 

 

 

 

  

posted @ 2017-12-14 14:28  Akmpfen  阅读(288)  评论(0)    收藏  举报