程序设计能力实训资料准备

程序设计能力实训 资料准备

注意:C++限定。

高精度

//加法(非负)

inline string add(string s1, string s2)

{

    string s;

    int len1 = s1.size(), len2 = s2.size();

    if (len1 < len2)

        for (int i = 1; i <= len2-len1; ++i)

            s1 = "0" + s1;

    else

        for (int i = 1; i <= len1-len2; ++i)

            s2 = "0" + s2;

    len1 = s1.size();

    int plus = 0, tmp;

    for (int i = len1-1; i >= 0; --i)

    {

        tmp = s1[i]-'0' + s2[i]-'0' + plus;

        plus = tmp / 10;

        tmp %= 10;

        s = char(tmp+'0') + s;

    }

    if (plus) s = char(plus+'0') + s;

    return s;

}

//减法

inline int cmp(const string& s1, const string& s2)

{

    if (s1.size() > s2.size()) return 1;

    else if (s1.size() < s2.size()) return -1;

    else return s1.compare(s2);

}

inline string subtract(string s1, string s2)

{

    string s;

    if (!cmp(s1, s2)) return "0";

    if (cmp(s1, s2) < 0) {putchar('-'); swap(s1, s2);}

    int tmp = s1.size() - s2.size(), minus = 0;

    for (int i = s2.size()-1; i >= 0; --i)

    {

        if (s1[i+tmp] < s2[i]+minus)

        {

            s = char(s1[i+tmp] - s2[i] - minus + '0'+10) + s;

            minus = 1;

        } else

        {

            s = char(s1[i+tmp] - s2[i] - minus + '0') + s;

            minus = 0;

        }

    }

    for (int i = tmp-1; i >= 0; --i)

    {

        if (s1[i] - minus >= '0')

        {

            s = char(s1[i]-minus) + s;

            minus = 0;

        } else

        {

            s = char(s1[i] - minus + 10) + s;

            minus = 1;

        }

    }

    s.erase(0, s.find_first_not_of('0'));

    return s;

}

//乘法(非负)(需要前面的add)

inline string mul(string s1, string s2)

{

    string s, stmp;

    int len1 = s1.size(), len2 = s2.size();

    for (int i = len2-1; i >= 0; --i)

    {

        stmp = "";

        int tmp = s2[i]-'0', plus = 0, t = 0;

        if (tmp)

        {

            for (int j = 1; j <= len2-i-1; ++j)

                stmp += "0";

            for (int j = len1-1; j >= 0; --j)

            {

                t = (tmp*(s1[j]-'0') + plus) % 10;

                plus = (tmp*(s1[j]-'0') + plus) / 10;

                stmp = char(t+'0') + stmp;

            }

            if (plus) stmp = char(plus+'0') + stmp;

        }

        s = add(s, stmp);

    }

    s.erase(0, s.find_first_not_of('0'));

    if (s.empty()) s = "0";

    return s;

}

//阶乘

void fact(int n)

{

    int result[10005];

    memset(result, 0, sizeof(result));

    result[0] = 1;

    for (int i = 2; i <= n; ++i)

    {

        int left = 0;

        for (int j = 0; j < 10000; ++j)

        {

            result[j] = left + result[j] * i;

            left = result[j] / 10;

            result[j] %= 10;

        }

    }

    int k = 9999;

    while (!result[k])

        k--;

    for (int i = k; i >= 0; --i)

        printf("%d", result[i]);

    printf("\n");

}

除法比较特殊,单独拿出来(非负,需要前面的subtractmul,除数不能为0):

inline void div(string s1, string s2, string& quot, string& rem)

{

    quot = rem = "";

    if (s1 == "0")

    {

        quot = rem = "0";

        return;

    }

    int comp = cmp(s1, s2);

    if (comp < 0)

    {

        quot = "0";

        rem = s1;

        return;

    }else if (!comp)

    {

        quot = "1";

        rem = "0";

        return;

    } else

    {

        int len1 = s1.size(), len2 = s2.size();

        string stmp;

        stmp.append(s1, 0, len2-1);

        for (int i = len2-1; i < len1; ++i)

        {

            stmp += s1[i];

            stmp.erase(0, stmp.find_first_not_of('0'));

            if (stmp.empty()) stmp = "0";

            for (char c = '9' ; c >= '0'; --c)

            {

                string s, tmp;

                s += c;

                tmp = mul(s2, s);

                if (cmp(tmp, stmp) <= 0)

                {

                    quot += c;

                    stmp = subtract(stmp, tmp);

                    break;

                }

            }

        }

        rem = stmp;

    }

    quot.erase(0, quot.find_first_not_of('0'));

    if (quot.empty()) quot = "0";

}

大整数类

struct BigInteger

{

    static const int BASE = 1e8;

    static const int WIDTH = 8;

    vector s;

    BigInteger(long long num = 0) { *this = num; }

    BigInteger operator = (long long);

    BigInteger operator = (const string&);

    BigInteger operator + (const BigInteger&) const;

    BigInteger operator - (const BigInteger&) const;

    BigInteger operator * (const BigInteger&) const;

    BigInteger operator / (const BigInteger&) const;

    BigInteger operator += (const BigInteger&);

    BigInteger operator -= (const BigInteger&);

    BigInteger operator *= (const BigInteger&);

    BigInteger operator /= (const BigInteger&);

    bool operator < (const BigInteger&) const;

    bool operator > (const BigInteger&) const;

    bool operator <= (const BigInteger&) const;

    bool operator >= (const BigInteger&) const;

    bool operator != (const BigInteger&) const;

    bool operator == (const BigInteger&) const;

};

BigInteger BigInteger::operator = (long long num)      //重载=运算符(数字赋值)

{

    s.clear();

    do

    {

        s.push_back(num%BASE);

        num /= BASE;

    }while (num > 0);

    return *this;

}

BigInteger BigInteger::operator = (const string& str)      //重载=运算符(字符串赋值)

{

    s.clear();

    int x, len = (str.length() - 1) / WIDTH + 1;

    for (int i = 0; i < len; ++i)

    {

        int end = str.length() - i * WIDTH;

        int start = max(0, end-WIDTH);

        sscanf(str.substr(start, end-start).c_str(), "%d", &x);

        s.push_back(x);

    }

    return *this;

}

BigInteger BigInteger::operator + (const BigInteger& b) const      //重载+运算符

{

    BigInteger c;

    c.s.clear();

    for (int i = 0, g = 0; ; ++i)

    {

        if (!g && i >= s.size() && i >= b.s.size())

            break;

        int x = g;

        if (i < s.size())

            x += s[i];

        if (i < b.s.size())

            x += b.s[i];

        c.s.push_back(x%BASE);

        g = x / BASE;

    }

    return c;

}

BigInteger BigInteger::operator += (const BigInteger& b)        //重载+=运算符

{

    *this = *this + b;

    return *this;

}

bool BigInteger::operator < (const BigInteger& b) const    //重载<运算符

{

    if (s.size() != b.s.size())

        return s.size() < b.s.size();

    for (int i = s.size()-1; i >= 0; --i)

        if (s[i] != b.s[i])

            return s[i] < b.s[i];

    return false;

}

bool BigInteger::operator > (const BigInteger& b) const    //重载>运算符

{

    return b < *this;

}

bool BigInteger::operator <= (const BigInteger& b) const    //重载<=运算符

{

    return !(b < *this);

}

bool BigInteger::operator >= (const BigInteger& b) const    //重载>=运算符

{

    return !(*this < b);

}

bool BigInteger::operator != (const BigInteger& b) const    //重载!=运算符

{

    return b < *this || *this < b;

}

bool BigInteger::operator == (const BigInteger& b) const    //重载==运算符

{

    return !(b < *this) || !(*this < b);

}

ostream& operator << (ostream& out, const BigInteger& x)        //重载<<运算符

{

    out << x.s.back();

    for (int i = x.s.size()-2; i >= 0; --i)

    {

        char buf[20];

        sprintf(buf, "%08d", x.s[i]);

        for (int j = 0; j < strlen(buf); ++j)

            out << buf[j];

    }

    return out;

}

istream& operator >> (istream& in, BigInteger& x)      //重载>>运算符

{

    string s;

    if (!(in >> s))

        return in;

    x = s;

    return in;

}

快速幂取模

typedef long long ll;

ll pow_mod(int a, int b, int p)

{

    ll ret = 1;

    while (b)

    {

        if (b&1) ret = (ret * a) % p;

        a = (a * a) % p;

        b >>= 1;

    }

    return ret;

}

扩展欧几里得

int extgcd(int a, int b, int &x, int &y)

{

    if (!b)

    {

        x = 1; y = 0;

        return a;

    }

    int d = extgcd(b, a % b, x, y);

    int t = x;

    x = y;

    y = t - a / b * y;

    return d;

}

素数相关

//欧拉筛

const int maxn = 1e7+5;

bool np[maxn]{true,true};

vector<int> prime;

int main()

{

    int n, m, x;

    cin >> n >> m;

    for (int i = 2; i <= n; ++i)

    {

        if (!np[i]) prime.push_back(i);

        for (int j = 0; j < prime.size() && i*prime[j] <= n; ++j)

        {

            np[i*prime[j]] = true;

            if (i % prime[j] == 0) break;

        }

    }

    for (int i = 1; i <= m; ++i)

    {

        scanf("%d", &x);

        printf("%s\n", np[x] ? "No" : "Yes");

    }

    return 0;

}

//埃氏筛

const int maxn = 1e6+5;

bool np[maxn]{true, true};

void init()

{

    for (int i = 2; i < maxn; i++)

        if (!np[i])

        {

            if (i > maxn/i) continue; //或用ll省去这一步

            for (int j = i*i; j < maxn; j += i)

                np[j] = true;

        }

}

//单独判断 O(sqrt(n))

typedef long long ll;

inline bool isprime(ll m)

{

    for (ll i = 2; i * i <= m; ++i)

        if (!(m % i)) return false;

    return true;

}

//区间筛

typedef long long ll;

const int maxn = 1e6+5;

ll a, b;

bool isp[maxn], ispsmall[maxn];

void seg_sieve()

{

    for (ll i = 2; i*i <= b; ++i) ispsmall[i] = true;

    for (ll i = 0; i <= b-a; ++i) isp[i] = true;

    for (ll i = 2; i*i <= b; ++i)

        if (ispsmall[i])

        {

            for (ll j = (i<<1); j*j <= b; j += i) ispsmall[j] = false;

            for (ll j = max(2LL, (a+i-1)/i) * i; j <= b; j += i) isp[j-a] = false;

        }

    if (a <= 1) isp[1-a] = false;

    bool flag = false;

    for (ll i = 0; i <= b-a; ++i)

        if (isp[i])

        {

            if (flag) printf(" %lld", i+a);

            else flag = true, printf("%lld", i+a);

        }

    flag ? puts("") : puts("no prime number.");

}

约瑟夫

int n, m;

vector<int> v;

int main()

{

    cin >> n >> m;

    if (!n && !m) return 0;

    for (int i = 1; i <= n; ++i)

        v.push_back(i);

    int kill = 0;

    while (v.size() > 1)

    {

        kill = (kill+m-1) % v.size();

        printf("%d ", v[kill]);

        v.erase(v.begin()+kill);

    }

    printf("%d\n", v[0]);

    return 0;

}

组合数计算

typedef long long ll;

ll C[41][41];

void calc()

{

    C[1][0] = C[1][1] = 1;

    for(int i = 2; i <= 40; ++i)

    {

        C[i][0] = 1;

        for(int j = 1; j <= i; ++j)

            C[i][j] = C[i-1][j] + C[i-1][j-1];

    }

}

LIS(nlogn)

fill(f, f+n, INF);

for (int i = 0; i < n; ++i)

    *lower_bound(f, f+n, a[i]) = a[i];

printf("%d\n", lower_bound(f, f+n, INF) - f);

闰年判断

bool is_leap(int n)

{

    return ((n % 4 == 0 && n % 100)|| n % 400 == 0) ? 1 : 0;

}

输出给定日期是星期几

int main()

{

    int y, m, d;

    scanf("%d-%d-%d", &y, &m, &d);

    if (m == 1 || m == 2){

        --y;

        m += 12;

    }

    int c = y / 100;

    int yy = y - c * 100;

    int day = yy + yy / 4 + c / 4 - 2 * c + 13 * (m + 1) / 5 + d - 1;

    if (y <= 1582 && m <= 10 && d <= 4) day += 3;

    while (day < 0) day += 7;

    day %= 7;

    switch(day){

    case 1: printf("Monday\n");break;

    case 2: printf("Tuesday\n");break;

    case 3: printf("Wednesday\n");break;

    case 4: printf("Thursday\n");break;

    case 5: printf("Friday\n");break;

    case 6: printf("Saturday\n");break;

    default: printf("Sunday\n");

    }

    return 0;

}

一些巧算方法

//n!低位0的个数

int main()

{

    int t,i,n,m,z;

    scanf("%d", &t);

    for (i = 0; i < t; i++){

        scanf("%d", &n);

        m = 5;z = 0;

        while (n >= m){

            z += n / m;

            m *= 5;

        }

        printf("case #%d:\n%d\n", i, z);

    }

    return 0;

}

//n!最高位

int main()

{

    int n,fn;

    double log_n_fac;

    while (scanf("%d", &n) != EOF){

        log_n_fac = 0.5 * log10(2 * PI *(double)n) + (double)n * log10((double)n / E);

        log_n_fac -=(int)log_n_fac;

        fn = pow(10, log_n_fac);//Stirling's approximation

        switch(n){

            case 0:printf("1\n");break;

            case 1:printf("1\n");break;

            case 2:printf("2\n");break;

            case 3:printf("6\n");break;

            case 7:printf("5\n");break;

            case 8:printf("4\n");break;

            default:printf("%d\n", fn);

        }

    }

    return 0;

}

//n^n最高位

int main()

{

    int n;

    scanf("%d",&n);

    while(n != 0){

        printf("%d\n",(int)pow(10,n*log10(n)-(int)(n*log10(n))));

        scanf("%d",&n);

    }

    return 0;

}

质因子分解

int n;

void solve(){

    int i;

    int m = n;

    for (i = 2; i <= n; i++){

        int cnt = 0;

        if (m % i) continue;

        while (m % i == 0){

            m /= i;

            cnt++;

        }

        printf("(%d,%d)", i, cnt);

        if (m == 1) break;

    }

    printf("\n");

}

最长回文子串

//中心扩展法

string expand(string s, int c1, int c2) {

    int l = c1, r = c2;

    int n = s.size();

    while (l >= 0 && r <= n-1 && s[l] == s[r])

        l--, r++;

    return s.substr(l+1, r-l-1);

}

string lps(string s) {

    int n = s.size();

    if (!n) return "";

    string lungo = s.substr(0, 1);

    for (int i = 0; i < n-1; i++) {

        string p1 = expand(s, i, i);

        if (p1.size() > lungo.size())

            lungo = p1;

        string p2 = expand(s, i, i+1);

        if (p2.size() > lungo.size())

            lungo = p2;

    }

    return lungo;

}

最大区间和

ans = a[0];

for (i = 0; i < n; ++i){

    if (tot > 0) tot += a[i];

    else tot = a[i];

    ans = (tot>ans)?tot:ans;

}

小型分数模板

struct frac

{

    ll nume, deno;

    ll gcd(ll a, ll b)

    {

        a = abs(a); b = abs(b);

        return b ? gcd(b, a % b) : a;

    }

    void reduct()

    {

        if(!nume) {

            deno = 1;

            return;

        }

        ll g = gcd(nume, deno);

        nume /= g; deno /= g;

        return;

    }

    frac(ll a, ll b = 1)

    {

        nume = a; deno = b;

        (*this).reduct();

    }

    void print()

    {

        if(deno == 1) printf("%lld\n", nume);

        else printf("%lld/%lld\n", nume, deno);

    }

};

frac operator+(const frac& a, const frac& b)

{

    frac ret(a.nume*b.deno + b.nume*a.deno, a.deno*b.deno);

    ret.reduct();

    return ret;

}

简单DP

//01背包

for (i = 0; i < n; ++i)

    for (j = m; j >= w[i]; --j)

        dp[j] = max(dp[j], dp[j-w[i]] + c[i]);

//最大上升子序列和(n^2)

for (i = 0; i < n; ++i)

    dp[i] = a[i];

nowmax = a[0];

for (i = 0; i < n; ++i)

    for (int j = 0; j < i; ++j)

        if (a[j] < a[i])

        {

            dp[i] = max(dp[i], dp[j] + a[i]);

            nowmax = max(nowmax, dp[i]);

        }

//整数拆分

for (i = 1; i <= n; ++i)

    for (j = 2; j <= n; ++j)

    {

        dp[i][j] = dp[i][j - 1];

        if (i == j) ++dp[i][j];

        else if(i > j) dp[i][j] += dp[i - j][j];

    }

//拆成2的幂和

for (int i = 3; i <= 1000000; ++i)

{

    if (i & 1) dp[i] = dp[i-1] % mod;

    else dp[i] = (dp[i-2] + dp[i>>1]) % mod;

}

//拆成不重复正整数

dp[0] = 1;

for (int i = 1; i <= m; ++i)

    for (int j = n; j >= i; --j)

        dp[j] += dp[j-i];

//数塔(和最小)

for (i = n-1; i >= 0; --i)

    for (j = 0; j <= i; ++j)

        dp[j] = min(dp[j], dp[j+1]) + a[i][j];

//数塔(和的个位数最大)

for (i = 0; i < n; ++i)

    dp[n-1][i][a[n-1][i] % 10] = 1;

for (i = n-2; i >= 0; --i)

    for (j = 0; j <= i; ++j)

        for (k = 0; k < 10; ++k)

            if (dp[i+1][j][k] || dp[i+1][j+1][k])

                dp[i][j][(k + a[i][j]) % 10] = 1;

for (i = 9; i >= 0; --i)

    if (dp[0][0][i]){printf("%d\n", i); break;}

//装箱问题(dp)

for (i = 0; i < n; ++i)

{

    scanf("%d", &w);

    for (j = m; j >= w; --j)

        dp[j] = max(dp[j], dp[j-w] + w);

}

//装箱问题(搜索)

void dfs(int cnt, int now)

{

    if (now > v) return;

    if (cnt == n + 1){

        if (now > max) max = now;

        return;

    }

    dfs(cnt + 1, now);

    dfs(cnt + 1, now + a[cnt]);

}

十六进制加法

const int N = 233;

struct bigNum{

    int a[N];

    bigNum(){

        memset(a,sizeof(a),0);

        for (int i=0;i

    }

    void print(){

        for (int i = a[0]; i>0; i--){

            printf("%X",a[i]);

        }

        puts("");

    }

    bigNum operator + (const bigNum &b){

        bigNum c;

        c.a[0] = max(a[0], b.a[0]);

        int x = 0;

        for (int i=1;i<=c.a[0];i++){

            //printf("b[i] = %d", b.a[i]);

            x += a[i] + b.a[i];

            c.a[i] = x % 16;

            x /= 16;

        }

        if (x) c.a[++c.a[0]] = x;

        return c;

    }

}a, b;

int qd(char x){

    if ('0' <= x && x <= '9')return x - '0';

    return x - 55;

}

bigNum jd(string st){

    bigNum ans;

    ans.a[0] = st.length();

    for (int i=1; i <= ans.a[0]; i++){

        ans.a[i] = qd(st[ans.a[0] - i]);

    }

    return ans;

}

int main(){

    int T;scanf("%d", &T);

    string st1, st2;

    for (int cas = 0;cas < T;cas++){

        printf("case #%d:\n", cas);

        cin >> st1 >> st2;

        a = jd(st1);

        b = jd(st2);

        bigNum c = a + b;

        c.print();

    }

    return 0;

}

部分库函数

int isgraph(int ch)                            是否是可打印字符(不含空格)

int isprint(int ch)                            是否是可打印字符(含空格)

int ispunct(int ch)

double atan2(double y, double x)                y/x的反正切(弧度)

int atoi(char *nptr)

double strtod(char *str)

int sscanf(char str, char *format)              通过str格式化赋值

char strcpy(char* dest, char* src)

char strcat(char* dest, char* src)

char strchr(const char *s1, int c)

int strcmp(const char* s1, const char* s2)      返回s1-s2

int strncmp(const char* s1, const char* s2, size_t maxlen)

char strrev(char *s)

char strstr(const char* s1, const char* s2)    s2中第一次出现s1的位置

string s(cstr[, chars_len]);

string s(num, c);

{

string s(“abcd”);

s.compare(“abcd”); //0

s.compare(“dcba”); //<0

s.compare(“ab”); //>0

s.compare(0,2,s,2,2); //比较ab和cd <0

}

s.assign(“nico”,5);//’n’’i’’c’’o’’\0’

s.insert(1,str);//插入到索引前

s.replace(1,2,”nternationalizatio”);//从1开始的2个s.erase(13);//从13开始往后全删除

s.erase(7,5);//从7开始往后删5个

string::find系列:

1. 搜索对象

2. [起点索引]

3. [搜索字符个数]

编程注意点

1.一般用C语言节约空间,要用C++库函数或STL时才用C++;

cout、cin和printf、scanf最好不要混用。

2.有时候int型不够用,可以用long long或__int64型(两个下划线__)。

值类型表示值介于 -2^63 ( -9,223,372,036,854,775,808) 到2^63-1(+9,223,372,036,854,775,807 )之间的整数。

printf("%I64d",a);

printf("%lld",a);

3.OJ判断是只看输出结果的。

所以大部分题处理一组数据后可以直接输出,就不需要用数组保存每一个Case的数据。

while(case--)

{scanf(...);

......

printf(...);

}

4.纯字符串用puts()输出。

数据大时最好用scanf()、printf()减少时间。

先用scanf(),再用gets()会读入回车。

scanf("%c%c",&c1,&c2)会读入空格;

5. 读到文件的结尾,程序自动结束

while( ( scanf(“%d”,&a) ) != -1 )

while( ( scanf(“%d”,&a) ) != EOF)

while( ( scanf(“%d”,&a) ) == 1 )

读到一个0时,程序结束

while( scanf(“%d”,&a) &&a)

读到多个0时,程序结束

while( scanf(“%d%d%d”,&a,&b,&c)&&a+b+c )

6.数组定义int a[10]={0};可以对其全部元素赋值为0;

全局变量,静态变量自动初始化为0;

7.有很多数学题是有规律的,直接推公式或用递归、循环。

8.圆周率=cos(0.0)

自然对数=exp(1.0)

9.如果要乘或除2^n,用位移运算速度快。a>>n;a<<n;

10.定义数组时,数组大小最好比告诉的最大范围大一点。字符数组大小必须比字符串最大长度大1。处理字符数组时不要忘了在最后加'\0'。

11.擅用三目运算符

int max(int a,int b)

{return a>b?a:b;

}

int gcd(int m,int n)

{return n?gcd(n,m%n):m;

}

 int abs(int a)

{return a<0?-a:a;

}

12.将乘法转换成加法减少时间

log(a*b)=log(a)+log(b)

将乘法转换成除法防止溢出

a/(b*c)=a/b/c

13.排序要求不高时可以用C++的STL模板函数sort(),stable_sort()

int a[n]={...};

sort(a,a+n);

bool cmp(int m,int n)

{return m>n;

}

sort(a,a+n,cmp);

14.有的题数据范围小但是计算量大可以用打表法

先把结果算出来保存在数组里,要用时直接取出来。

1.输入输出

ACM和TopCoder不同,TopCoder只用让参赛者写一个class,而ACM需要参赛者完成整个console程序.在TopCoder中,输入输出是通过parameter传递的,不用过多考虑,在ACM中,却需要自己编写.

(1).只有一组输入时,这种情况不用我说了,都会,但是通常也不会有这么水的题

(2).固定组数的输入,可以利用一个计数器和while语句完成,

01 #include <iostream>

02 

03 int main(void){

04     int n;

05     scanf("%d", &n);

06     while (n--){

07         //...

08     }

09     //...

10     return 0;

11 }

(3).测试数据结尾有标志字符(例如最后一组输入后给一个0),这个只用加一个if语句判断读入的数据是什么,是结束标志跳出就ok了.也不多说了

(4).题目没有告诉你有多少组数据,这个通常是最令新手疑惑的,这种情况,一般用文件结束标志EOF判断

01 #include <iostream> 

02 

03 int main(void){

04     int n;

05     while (scanf("%d", &n) != EOF){

06     //...

07     } 

08     //...

09     return 0;

10 }

其实这里也可以用c++的cin输入流判断,例如

01 #include <iostream>

02 

03 using namespace std;

04 

05 int main(void){

06     int n;

07     while (cin>>n){

08     //...

09     } 

10     //...

11     return 0;

12 }

但是这样不是特别好,为什么?下面会说.

对于输出,最好采用的接收一组数据,处理一组数据,把结果保存在一个缓冲数组中,待所有输入结束后,再一起输出,而不是待接收完所有输入后,再处理,再输出,这样会消耗更多的memory,而且会更慢.

2.关于效率

第一,上面的所有例子,均采用的c标准I/O,为什么不用c++的cin,cout呢?是有原因的,经实践,在大规模输入输出下,cin,cout效率远远低于scanf()和printf(),原因据我估计应该是以为scanf(),printf()是汇编写的(这点可以从这两个函数均可以接受任意多组parameter(s)看出,c/c++函数是不具备这样的性质的),而cin,cout均是直接c/c++写的流操作,本来c/c++就比汇编慢,还引入流,所以自然比scanf(),printf()慢了.因此,在输入输出数据量很小的情况下,出于方便的原因,可以采用cin,cout,而在输入输出数据量比较大的情况下用scanf(),printf()比较保险,避免超时.

第二.ACM中,除了c/c++,一般还支持java等语言,但是由于java是解释执行的,效率十分低下,为此,一般的JudgeOnline都把java的time limit设置为题目给定值(也就是c/c++的time limit)的三倍,而且给每一组输入再额外提供150ms.即使是这样,java遇上复杂或者高精度计算的题目,还是很容易超时,因为效率有时候还远远未到c/c++的1/3.因此,一般来说,除了个别java极其有利的情况(例如字符串处理),不建议使用java.

3.关于调试

(1)调试的时候可以使用重定向,从文件中读入数据、直接将答案输出到文件中。

例如:

       以读的方式打开输入文件:freopen(“txtin.txt”,”r”,stdin);

       以写的方式打开输出文件:freopen(“txtin.txt”,”w”,stdout);

但是需要注意的是,再提交代码的时候一定要记得将以上两句与文件操作有关的代码去掉,否在系统会因找不到对应的文件而出错。

(2)题目一般给出的测试数据都是较少的,为了验证程序的正确性,要自己多设几组测试数据,尤其不要忘记了边界值的处理,边界往往会是容易出错的地方。

(3)再写计算公式的时候,若等式两边的类型不一样要特别注意类型转换,否常常会得到一个错误的结果。比如,int a,b; double c;

c=a/b;若a可以整除b则答案是正确的,否在a/b的结果只取结果的整数部分,并不会自动转换为double类型。正确的写法应该是c=(double)a/b,这样才会得到正确的答案。

还有再调用一些数学函数的时候,比如floor(),应该注意的是其参数是double型的,再调用时应该写为floor((double)a/b);否在a/b自动取整,floor函数并不起作用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容