初次了解常数优化

转载:https://blog.csdn.net/qq_33583069/article/details/53086992
https://blog.csdn.net/xuxiayang/article/details/81021585

一、
某些时候,如果你优化到无法再优化的时候
尝试去自己重新实现库函数。

比如

isdigit()
max()/min()
unique()/lower_bound()/upper_bound()
scanf()/printf()
cin/cout
getchar()/putchar()
STL::queue/stack/priority_queue/deque

二、常数优化:
位运算

没有O2的时候(有O2不用管。编译器会帮你)
x*10 <=> (x<<3)+(x<<1)
x!=y <=> x^y
x!=-1 <=> ~x
x*2 <=> x<<1
x*2+1 <=> x<<1|1
x/2 <=> x>>1
(x+1)%2 <=> x^1
x%2 <=> x&1
x%2==0 <=> ~(x&1)

三、语法
inline 在非递归函数前加修饰。
循环变量 int i =>register int i

c++没有尾递归优化。所以可以自己手写栈来优化递归。

原则上尽量减少乘/除/取模 指令
取模指令如果是逐渐累加的话,

x+=add;x%=mod;
=> x+=add;x>=mod?x%=mod:1;

A?B:C 好像要比if,else语句快。

memset初始化细节 memset(a,0x3f,sizeof(a));
最后的a[1] = 0x3f3f3f3f
int的极限是 0x7fffffff
还可以~0u
INF有的时候不要刚好赋值到0X7FFFFFFF,如果有2个inf的值相加就会溢出。

乘法溢出。
这个要注意。不要直接全部long long这样慢很多

四、读入优化
非众所周知,对于C++来说有三种常见的读入方式即:cin,scanf,read(快读),这几种读入方式各有优点和缺点,这里简单提一下

cin,C++标准的读入方式,读入字符串有得天独厚的优势,适应性强,使用简单,方便,可以文件输入同步,缺点是速度十分慢
scanf,适合格式化输入:擅长精度控制、隔行输入等十分方便,常用于处理一些数字中间掺和符号的读入,但处理字符串没有cin方便,但速度比cin快很多,功能复杂多样,是C++最常见的读入方式。
read,又称读入优化,其优化原理是基于C++getchar运算速度非常快,可以实现高效率读入大规模数据,且就有很强的伸缩性,可以在其函数内进行一些特判,例如跳过字母等等,缺点是对新手来说有点难理解,是中高阶选手普遍普遍使用的读入方式,缺点是输入单一,处理数据功能弱

代码片段
函数形式

int read()
{
    int d=1;//符号
    int f=0;//结果
    char c;//加速关键
    while(c=getchar(),c<=47||c>=58)/*在这里你可以加入一些判断,例如遇到负号将d赋值为-1,或者
    遇到换行标记等等*/
    f=(f<<3)+(f<<1)+c-48;//位运算加速,等下会在后面的位运算优化中提到
    while(c=getchar(),c>=48&&c<=57) f=(f<<3)+(f<<1)+c-48;//保存数字
    return f*d;//这里乘d是处理负数专用
}

过程形式

void read(int &f)//因为我们需要把快读的结果返回给f,所以要加地址符&
{
    char c;int d=1;f=0;//下面的基本一致
    while(c=getchar(),c<=47||c>=58);
    f=(f<<3)+(f<<1)+c-48;//相当于f*10+c-48
    while(c=getchar(),c>=48&&c<=57) f=(f<<3)+(f<<1)+c-48;
    return;
}

究极优化版本

#define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++)
char BB[1<<15],*S=BB,*T=BB;;
IL LL read()
{
    f=0;Re char c; 
    while(c=getchar(),c<=47||c>=58);f=(f<<3)+(f<<1)+c-48;
    while(c=getchar(),c>=48&&c<=57) f=(f<<3)+(f<<1)+c-48;
    return f;
}

五、输出优化
非众所周知,C++也有三种常见的三种输出方式cout,printf,write(输出流),这三种输出方式分别对应cin,printf,read,速度排序也基本一致

cout,C++标准的输出方式,简单通俗易懂,使用方便,速度慢
printf,格式化输出神奇,场宽,精度等操作统统适用,且可以在里面插加字符
write,基于C++putchar输出神搜的输出算法,可以在log10(n)的时间内高速输出一个数字,且可以处理__int128,缺点是输出范围狭小。

程序片段
基本程序

void write(int x)
{
    /*在这一行你可以进行一些特殊处理和判断,例如处理负数等*/
    if(x>9) write(x/10);//能分解则分解
    putchar(x%10+48);//利用C++putchar速度快的因素加速输出
}

改造输出优化,需搭配上面的进行
1.输出后空格

void writespace(int x)
{
    write(x);putchar(32);return;//这里仍然利用了puchar速度快的优点
}

2.输出后换行

void writeln(int x)
{
    write(x);putchar(10);//依旧利用putchar快速的优点,达到十分快速的效果
}

六、位运算优化
众所周知,所有的电脑信息处理都是基于二进制的,冯诺依曼先生提出的这个思想给我们又带来了优化的契机,在C++中,加减乘除等运算的运行效率实在不敢恭维,特别是mod运算更是慢的可怜,所以在很多时候,我们可以运用到位运算进行速度优化,具体做法这里就不多说了,就是尽量把代码中的运算多使用二进制进行,这会让你的代码运行飞快

七、诡异的优化
在所有的int前加上register,在所有的void和funcition前加上inline,把主程序的int改成signed就可以达到一个十分诡异的速度!

猜你喜欢

转载自blog.csdn.net/qq_36386435/article/details/81566646