基础语法

ACM一些可能需要的知识在这里简单介绍一下:


一、 64bit整数问题

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

    例1:An Easy Problem

#include<stdio.h>
int main(){
    long long sum[100002],i;    //注意i用long long
    sum[0]=0;
    int n;
    for(i=1;i<=100000;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){
        if(n<0)
            break;
        printf("%I64d\n",sum[n]);
    }
    return 0;
}
View Code

二、大数组RE问题

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

    例2:Density of Power Network

#include <iostream>
#include <iomanip>
#include <cstring> 
using namespace std;

int startBus[505], endBus[505], flag[505][505];

int main(int argc, char *argv[])
{
    int T, numLine, numBus, line;
    double ratio;

    cin >> T;
    while(T--){
        memset(flag,0, sizeof(flag));
        cin >> numBus >> numLine;
        for(int i=0; i<numLine; i++){
            cin >> startBus[i];
        }
        for(int i=0; i<numLine; i++)
            cin >> endBus[i];
            
        line = 0;
        for(int i=0; i<numLine; i++){
            if(!flag[startBus[i]][endBus[i]])
                line ++;
            flag[startBus[i]][endBus[i]] = flag[endBus[i]][startBus[i]] = 1;
        }
        ratio = (double)line/numBus;
        cout<<setiosflags(ios::fixed)<<setprecision(3)<<ratio<<endl;
    }
    return 0;
}
View Code

更具体的可以参见luoxi同学的这篇日志。

http://hi.baidu.com/luoxi0209/blog/item/50364c39b1c2622597ddd8b0.html

三、大数组RE问题

    尽量使用scanf和printf (它们的格式化输出功能非常好)。如果字符串,尽量用变通的方式,当然也可以用cout。

四、精度问题

    对于float/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
}
对于float/double的取整也很有技巧:
floor和ceil不一定能给你你想要的结果(why?)对于一个double类型的a,想想这些表达式的意义:(提示:取(?)整,四舍五入)
(int)(a + EPS)
(int)(a + EPS + 0.5)
以上对于正数成立,对于负数呢?最好还是自己想想

    例3:Taxi Fare

#include <iostream>

using namespace std;
#define epsilon 0.0001

double GetFee(int dis, int t, bool isNew){
    double cost;
    
    cost = 0;
    if(isNew){
        if(dis < 3)
            cost += 11;
        else if(dis < 10)
            cost += (dis-3)*2.5 + 11;
        else
            cost += (dis-10)*3.75 + 2.5*7 + 11;
        
        cost += t/4.0*2.5;  
    }
    else{
        cost += 1;
        if(dis < 3)
            cost += 10;
        else if(dis < 10)
            cost += (dis-3)*2 + 10;
        else
            cost += (dis-10)*3 + 2*7 + 10;
        
        cost += t/5.0*2;   
    }
    return cost+epsilon;
}

int main(){
    int T, d, t, oldFee, newFee;

    cin >> T;
    while(T--){
        cin >> d >> t;
        newFee = (int)(GetFee(d, t, 1)+0.5);
        oldFee = (int)(GetFee(d, t,0)+0.5);
        cout<<newFee - oldFee<<endl;
    }
    return 0;
}
View Code

其它还有一些建议,比如
~ 定义数组的时候开大些
比如题目告诉最多5000个数据,那就开到5010或者更多一些吧

posted @ 2014-07-15 20:21  算法研究  阅读(86)  评论(0编辑  收藏  举报