ACM/OI中C++常用优化(实用/调试/技巧)代码(语法)
一、C++萬能編譯頭文件
#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++不支持)。
其他國外的oj,還有臺灣的oj都支持,CF,Topcoder也都支持。
2、降低編譯速度、造成CE。
主要用途:減少代碼量
二、預編譯
預處理宏
#define long long ll條件編譯
#define DEBUG int main(){#ifdef DEBUGcout << "Hello world!" << endl;#endifreturn 0;}C++/C語言中條件編譯相關的預編譯指令,包括??#define、#undef、#ifdef、#ifndef、#if、#elif、#else、#endif、defined。
#define ? ? ? ? ? ?定義一個預處理宏
#undef ? ? ? ? ? ?取消宏的定義
#if ? ? ? ? ? ? ? ? ? 編譯預處理中的條件命令,相當于C語法中的if語句
#ifdef ? ? ? ? ? ? ?判斷某個宏是否被定義,若已定義,執(zhí)行隨后的語句
#ifndef ? ? ? ? ? ?與#ifdef相反,判斷某個宏是否未被定義
#elif ? ? ? ? ? ? ? ?若#if, #ifdef, #ifndef或前面的#elif條件不滿足,則執(zhí)行#elif之后的語句,相當于C語法中的else-if
#else ? ? ? ? ? ? ?與#if, #ifdef, #ifndef對應, 若這些條件不滿足,則執(zhí)行#else之后的語句,相當于C語法中的else
#endif ? ? ? ? ? ? #if, #ifdef, #ifndef這些條件命令的結(jié)束標志.
defined?????? ?? 與#if, #elif配合使用,判斷某個宏是否被定義
?詳情
主要用途:替換、選擇性編譯
三、文件輸入/文件輸出
#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中繁瑣的復制/粘貼/輸入操作
四、程序運行時間
#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;}?詳情
注意:此代碼記錄輸入時間,故應該配合文件輸入/文件輸出代碼
主要用途:與文件輸入/文件輸出同時使用,初步計算程序運行時間
五、寄存器變量
register?常見宏編譯
#define RI register int對于一些頻繁使用的變量,可以聲明時加上該關鍵字,運行時可能會把該變量放到CPU寄存器中,只是可能,因為寄存器的空間是有限的,不保證有效。特別是你變量多的時候,一般還是丟到內(nèi)存里面的。?
比較下面兩段程序:
優(yōu)化:0.2826 second?
不優(yōu)化:1.944 second
?詳情
主要用途:減少程序運行時間
六、typedef
typedef long long ll; //typedef __int128 lll;?類似于宏編譯#define
#define long long ll; #define __int128 lll;?詳情
主要用途:減少代碼量
七、cin和cout取消同步
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);?詳情?
主要用途:減少輸入輸出的時間
八、快速輸入輸出函數(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();} }?詳情?
主要用途:減少輸入輸出的時間
九、endl、"\n"和'\n'
"\n"
"\n"表示搜索一個字符串,只有一個數(shù)據(jù)是回車符
'\n'
'\n' 表示一個字符,兩者在輸出上是一樣的!
endl
詳情
主要用途:提高程序運行效率
十、常量
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;主要用途:提高代碼復用性
十一、內(nèi)聯(lián)函數(shù)
inline inline int max(int a,int b) {return a > b ? a:b; }由編譯器在編譯時會在主程序中把函數(shù)的內(nèi)容直接展開替換,減少了內(nèi)存訪問,但是這并不是適用于各種復雜以及遞歸式的函數(shù),復雜函數(shù)編譯器會自動忽略inline?
詳情
主要用途:提高程序運行效率
十二、默認參數(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ù)復用性,減少代碼量
十三、奇偶判斷
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主要用途:提高程序運行效率
十四、乘和除的位運算
x <<= 1; x *= 2;例如上面這兩句,都是把x乘2,但真的用位運算會快么,其實他們理論上是一樣的,在被g++翻譯成匯編后,兩者的語句都是
addl %eax, %eax1它等價于 x = x + x。所以在這里位運算并沒有任何優(yōu)化。那么把乘數(shù)擴大呢,比如乘10,x *= 10的匯編語言為
leal (%eax,%eax,4), %eax addl %eax, %eax翻譯過來就是
x = x + x*4; x = x + x;而那些喜歡用(x << 3 + x << 1)的人自己斟酌!
?
但是位運算在某些地方是非常有用的,比如除法,右移的匯編代碼為
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可以看到,右移會比除快很多。
詳情
主要用途:提高程序運行效率
十五、變量交換
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主要用途:提高程序運行效率
十六、lowbit函數(shù)
x & (-x) int lowbit(int x) {return x&(-x); }詳情?
主要用途:提高程序運行效率
十七、2的冪判斷
x > 0 ? ( x & (x - 1)) == 0 : false詳情
主要用途:提高程序運行效率
十八、短路運算符
短路運算符:一旦可以確定了表達式的真假值時,直接返回真假值
詳情
主要用途:提高程序運行效率
十九、非零即真
if(x)詳情
主要用途:提高程序運行效率
二十、?取模優(yōu)化
//設模數(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ōu)化
用++i代替i++,后置++需要保存臨時變量以返回之前的值,在 STL 中非常慢。
詳情
主要用途:提高程序運行效率
二十二、結(jié)構(gòu)優(yōu)化
如果要經(jīng)常調(diào)用a[x],b[x],c[x]這樣的數(shù)組,把它們寫在同一個結(jié)構(gòu)體里面會變快一些,比如f[x].a, f[x].b, f[x].c?
指針比下標快,數(shù)組在用方括號時做了一次加法才能取地址!所以在那些計算量超大的數(shù)據(jù)結(jié)構(gòu)中,你每次都多做了一次加法!!!在 64 位系統(tǒng)下是 long long 相加,效率可想而知。
詳情
主要用途:提高程序運行效率
二十三、對拍程序
雖然肉眼debug的能力也很重要,但有的時候一直手打數(shù)據(jù)測試兩三天也沒有必要。
詳情
主要用途:提高DEBUG效率,尋找問題數(shù)據(jù)
二十四、O1,O2,O3編譯優(yōu)化
#pragma GCC optimize("O3") #pragma G++ optimize("O3")詳情
主要用途:提高程序運行效率
二十五、擴棧
C++版本一
寫在main的開始
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); }//在這里寫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)棧的存儲空間
二十六、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]));?詳情
主要用途:提高程序運行效率
二十七、YES/NO輸出(三元運算符)
cout<<(ans?"YES":"NO")<<endl;?詳情
主要用途:提高程序可讀性
二十八、輸出空格分隔、末尾無空格的數(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++庫函數(shù) (STL)
| 函數(shù) | 作用 |
| sort | 排序 |
| memset | 賦值 |
| next_permutation | 全排列 |
| max | 最大值 |
| min | 最小值 |
| swap | 交換 |
| exit | 退出程序 |
| __builtin_popcount | 一個數(shù)的二進制表示中有多少位是1 |
| strlen | 字符數(shù)組長度 |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
| ? | ? |
?詳情
主要用途:減少代碼量
參考文章:
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++常用优化(实用/调试/技巧)代码(语法)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 香甜的黄油 Sweet Butter
- 下一篇: s3c2440移植MQTT