ACM/OI中C++常用优化(实用/调试/技巧)代码(语法)
一、C++萬(wàn)能編譯頭文件
#include<bits/stdc++.h>從
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> using namespace std;int main(){cout << "Hello world!" << endl;return 0; }到
#include<bits/stdc++.h> using namespace std;int main(){cout << "Hello world!" << endl;return 0; }注意:
1、目前POJ還不支持<bits/stdc++.h>(G++、C++都不支持)。HDU部分支持(G++支持,C++不支持)。
其他國(guó)外的oj,還有臺(tái)灣的oj都支持,CF,Topcoder也都支持。
2、降低編譯速度、造成CE。
主要用途:減少代碼量
二、預(yù)編譯
預(yù)處理宏
#define long long ll條件編譯
#define DEBUG int main(){#ifdef DEBUGcout << "Hello world!" << endl;#endifreturn 0;}C++/C語(yǔ)言中條件編譯相關(guān)的預(yù)編譯指令,包括??#define、#undef、#ifdef、#ifndef、#if、#elif、#else、#endif、defined。
#define ? ? ? ? ? ?定義一個(gè)預(yù)處理宏
#undef ? ? ? ? ? ?取消宏的定義
#if ? ? ? ? ? ? ? ? ? 編譯預(yù)處理中的條件命令,相當(dāng)于C語(yǔ)法中的if語(yǔ)句
#ifdef ? ? ? ? ? ? ?判斷某個(gè)宏是否被定義,若已定義,執(zhí)行隨后的語(yǔ)句
#ifndef ? ? ? ? ? ?與#ifdef相反,判斷某個(gè)宏是否未被定義
#elif ? ? ? ? ? ? ? ?若#if, #ifdef, #ifndef或前面的#elif條件不滿足,則執(zhí)行#elif之后的語(yǔ)句,相當(dāng)于C語(yǔ)法中的else-if
#else ? ? ? ? ? ? ?與#if, #ifdef, #ifndef對(duì)應(yīng), 若這些條件不滿足,則執(zhí)行#else之后的語(yǔ)句,相當(dāng)于C語(yǔ)法中的else
#endif ? ? ? ? ? ? #if, #ifdef, #ifndef這些條件命令的結(jié)束標(biāo)志.
defined?????? ?? 與#if, #elif配合使用,判斷某個(gè)宏是否被定義
?詳情
主要用途:替換、選擇性編譯
三、文件輸入/文件輸出
#define DEBUG int main(){#ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout);#endifint n;scanf("%d",&n);//cout << "Hello world!" << endl;return 0;}?詳情
主要用途:減少DEBUG中繁瑣的復(fù)制/粘貼/輸入操作
四、程序運(yùn)行時(shí)間
#include<iostream> #include<ctime> using namespace std; #define DEBUG int main(){int n;scanf("%d",&n);//cout << "Hello world!" << endl;#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);#endifreturn 0;}?詳情
注意:此代碼記錄輸入時(shí)間,故應(yīng)該配合文件輸入/文件輸出代碼
主要用途:與文件輸入/文件輸出同時(shí)使用,初步計(jì)算程序運(yùn)行時(shí)間
五、寄存器變量
register?常見(jiàn)宏編譯
#define RI register int對(duì)于一些頻繁使用的變量,可以聲明時(shí)加上該關(guān)鍵字,運(yùn)行時(shí)可能會(huì)把該變量放到CPU寄存器中,只是可能,因?yàn)榧拇嫫鞯目臻g是有限的,不保證有效。特別是你變量多的時(shí)候,一般還是丟到內(nèi)存里面的。?
比較下面兩段程序:
優(yōu)化:0.2826 second?
不優(yōu)化:1.944 second
?詳情
主要用途:減少程序運(yùn)行時(shí)間
六、typedef
typedef long long ll; //typedef __int128 lll;?類(lèi)似于宏編譯#define
#define long long ll; #define __int128 lll;?詳情
主要用途:減少代碼量
七、cin和cout取消同步
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);?詳情?
主要用途:減少輸入輸出的時(shí)間
八、快速輸入輸出函數(shù)
template <class T> inline void scan_d(T &ret)? {char c;?ret = 0;while ((c = getchar()) < '0' || c > '9');while (c >= '0' && c <= '9'){?ret = ret * 10 + (c - '0'), c = getchar();} }?詳情?
主要用途:減少輸入輸出的時(shí)間
九、endl、"\n"和'\n'
"\n"
"\n"表示搜索一個(gè)字符串,只有一個(gè)數(shù)據(jù)是回車(chē)符
'\n'
'\n' 表示一個(gè)字符,兩者在輸出上是一樣的!
endl
詳情
主要用途:提高程序運(yùn)行效率
十、常量
const int N=1000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f;主要用途:提高代碼復(fù)用性
十一、內(nèi)聯(lián)函數(shù)
inline inline int max(int a,int b) {return a > b ? a:b; }由編譯器在編譯時(shí)會(huì)在主程序中把函數(shù)的內(nèi)容直接展開(kāi)替換,減少了內(nèi)存訪問(wèn),但是這并不是適用于各種復(fù)雜以及遞歸式的函數(shù),復(fù)雜函數(shù)編譯器會(huì)自動(dòng)忽略inline?
詳情
主要用途:提高程序運(yùn)行效率
十二、默認(rèn)參數(shù)
可用于逆元的取??焖賰绾瘮?shù)
int PowerMod(int a, int b=MOD-2, int c=MOD){int ans = 1;a = a % c;while(b>0){if(b % 2 == 1)ans = (ans * a) % c;b >>= 1;a = (a * a) % c;}return ans; }詳情
主要用途:提高函數(shù)復(fù)用性,減少代碼量
十三、奇偶判斷
n%2 n&1其中&1的效率高于%2
詳情
%2的匯編代碼為
movl _x, %eax movl $LC0, (%esp) movl %eax, %edx //(del) shrl $31, %edx //(del) addl %edx, %eax //(del) andl $1, %eax subl %edx, %eax //(del) movl %eax, 4(%esp) movl %eax, _x?&1的匯編代碼為
movl _x, %eax movl $LC0, (%esp) andl $1, %eax movl %eax, 4(%esp) movl %eax, _x主要用途:提高程序運(yùn)行效率
十四、乘和除的位運(yùn)算
x <<= 1; x *= 2;例如上面這兩句,都是把x乘2,但真的用位運(yùn)算會(huì)快么,其實(shí)他們理論上是一樣的,在被g++翻譯成匯編后,兩者的語(yǔ)句都是
addl %eax, %eax1它等價(jià)于 x = x + x。所以在這里位運(yùn)算并沒(méi)有任何優(yōu)化。那么把乘數(shù)擴(kuò)大呢,比如乘10,x *= 10的匯編語(yǔ)言為
leal (%eax,%eax,4), %eax addl %eax, %eax翻譯過(guò)來(lái)就是
x = x + x*4; x = x + x;而那些喜歡用(x << 3 + x << 1)的人自己斟酌!
?
但是位運(yùn)算在某些地方是非常有用的,比如除法,右移的匯編代碼為
movl _x, %eax sarl %eax movl %eax, _x movl _x, %eax而除二的匯編代碼為
movl _x, %eax movl %eax, %edx //(del) shrl $31, %edx //(del) addl %edx, %eax //(del) sarl %eax movl %eax, _x movl _x, %eax可以看到,右移會(huì)比除快很多。
詳情
主要用途:提高程序運(yùn)行效率
十五、變量交換
swap函數(shù)效率高于a ^= b ^= a ^= b
詳情
(a ^= b ^= a ^= b)的匯編代碼
movl _b, %edx movl _a, %eax xorl %edx, %eax xorl %eax, %edx xorl %edx, %eax movl %eax, _a xorl %eax, %eax movl %edx, _b(int t = a;a = b,b = t;)的匯編代碼
movl _a, %eax movl _b, %edx movl %eax, _b xorl %eax, %eax movl %edx, _a主要用途:提高程序運(yùn)行效率
十六、lowbit函數(shù)
x & (-x) int lowbit(int x) {return x&(-x); }詳情?
主要用途:提高程序運(yùn)行效率
十七、2的冪判斷
x > 0 ? ( x & (x - 1)) == 0 : false詳情
主要用途:提高程序運(yùn)行效率
十八、短路運(yùn)算符
短路運(yùn)算符:一旦可以確定了表達(dá)式的真假值時(shí),直接返回真假值
詳情
主要用途:提高程序運(yùn)行效率
十九、非零即真
if(x)詳情
主要用途:提高程序運(yùn)行效率
二十、?取模優(yōu)化
//設(shè)模數(shù)為 mod inline int inc(int x,int v,int mod){x+=v;return x>=mod?x-mod:x;}//代替取模+ inline int dec(int x,int v,int mod){x-=v;return x<0?x+mod:x;}//代替取模-詳情
主要用途:提高程序運(yùn)行效率
二十一、加法優(yōu)化
用++i代替i++,后置++需要保存臨時(shí)變量以返回之前的值,在 STL 中非常慢。
詳情
主要用途:提高程序運(yùn)行效率
二十二、結(jié)構(gòu)優(yōu)化
如果要經(jīng)常調(diào)用a[x],b[x],c[x]這樣的數(shù)組,把它們寫(xiě)在同一個(gè)結(jié)構(gòu)體里面會(huì)變快一些,比如f[x].a, f[x].b, f[x].c?
指針比下標(biāo)快,數(shù)組在用方括號(hào)時(shí)做了一次加法才能取地址!所以在那些計(jì)算量超大的數(shù)據(jù)結(jié)構(gòu)中,你每次都多做了一次加法!!!在 64 位系統(tǒng)下是 long long 相加,效率可想而知。
詳情
主要用途:提高程序運(yùn)行效率
二十三、對(duì)拍程序
雖然肉眼debug的能力也很重要,但有的時(shí)候一直手打數(shù)據(jù)測(cè)試兩三天也沒(méi)有必要。
詳情
主要用途:提高DEBUG效率,尋找問(wèn)題數(shù)據(jù)
二十四、O1,O2,O3編譯優(yōu)化
#pragma GCC optimize("O3") #pragma G++ optimize("O3")詳情
主要用途:提高程序運(yùn)行效率
二十五、擴(kuò)棧
C++版本一
寫(xiě)在main的開(kāi)始
int size = 256 << 20; // 256MB char *p = (char*)malloc(size) + size; __asm__("movl %0, %%esp\n" :: "r"(p));C++版本二
#pragma comment(linker, "/STACK:102400000,102400000")C++版本三
64位版本
extern int main2(void) __asm__ ("main2"); int main2(){ exit(0); }//在這里寫(xiě)main函數(shù) int main(){int size=64<<20; char *p=(char*)malloc(size)+size; __asm__ __volatile__("movq %0, %%rsp\n" "pushq $exit\n" "jmp main2\n" :: "r"(p)); }?
詳情
主要用途:提高系統(tǒng)棧的存儲(chǔ)空間
二十六、memset和memcpy以及memmove
函數(shù)效率都非常高,比循環(huán)的速度快很多
若原code:
for(int i=l;i<=r;++i) a[i]=0; for(int i=l;i<=r;++i) a[i]=b[i]; for(int i=l;l<=r;++i) a[i]=b[i],b[i]=0;則
memset(a+l,0,r-l+1<<2); memcpy(a+l,b+l,r-l+1<<2); memmove(a+l,b+l,r-l+1<<2); memset(a+l,0,(r-l+1)*sizeof(a[0])); memcpy(a+l,b+l,(r-l+1)*sizeof(a[0])); memmove(a+l,b+l,(r-l+1)*sizeof(a[0]));?詳情
主要用途:提高程序運(yùn)行效率
二十七、YES/NO輸出(三元運(yùn)算符)
cout<<(ans?"YES":"NO")<<endl;?詳情
主要用途:提高程序可讀性
二十八、輸出空格分隔、末尾無(wú)空格的數(shù)組
for(int i=1;i<=n;i++){printf("%d%c",a[i]," \n"[i==n]); }?詳情
主要用途:減少代碼量
二十九、構(gòu)造函數(shù)
struct node{int u,v,w;node(){};node(int u,int v,int w):u(u),v(v),w(w){} };?詳情
主要用途:減少代碼量
三十、常用C++庫(kù)函數(shù) (STL)
| 函數(shù) | 作用 |
| sort | 排序 |
| memset | 賦值 |
| next_permutation | 全排列 |
| max | 最大值 |
| min | 最小值 |
| swap | 交換 |
| exit | 退出程序 |
| __builtin_popcount | 一個(gè)數(shù)的二進(jìn)制表示中有多少位是1 |
| strlen | 字符數(shù)組長(zhǎng)度 |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
?詳情
主要用途:減少代碼量
參考文章:
https://www.cnblogs.com/xenny/p/9410888.html
https://blog.csdn.net/JacaJava/article/details/78336840
https://blog.csdn.net/chencsmat/article/details/47778757
?
總結(jié)
以上是生活随笔為你收集整理的ACM/OI中C++常用优化(实用/调试/技巧)代码(语法)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 香甜的黄油 Sweet Butter
- 下一篇: 湖南大学第十五届程序设计竞赛