前言
众所周知,有一些可(bian)爱(tai)的题单纯使用那些算法会T,所以需要用一些神奇的优化。
读入优化
既用过pascal,又用过c++的选手们都可以感受到知道,c++虽然快,但它的读入scanf()慢得一匹,cin>>就更不必说了。所以,在输入数据≥
的情况下,程序运行的时间基本上都在读入上了……
所以,有没有可能让c++掌握pascal的read()呢?
答案是肯定的。
因为,pascal的read()之所以快,就在于它是一个一个字符读入,然后再转化为数字的;所以c++的读入优化就是手动实现pascal的read()。
最基本的读入优化如下:
void read(int &x)
{
char ch=getchar(); x=0;
for(;ch<'0'||ch>'9';ch=getchar());
for(;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
}
当然,我们还可以装逼一点,使用下面这种打法:
#include<cctype>
void read(int &x)
{
char ch=getchar(); x=0;
for(;!isdigit(ch);ch=getchar());
for(;isdigit(ch);x=(x<<3)+(x<<1)+(ch^48),ch=getchar());
}
isdigit(x)判断x是否是0~9的整数 。
注意要用cctype头文件。
但是,如果你要读入int、long long这些不同的数据类型,又嫌打两个读入优化冗长的话,可以使用下面的神奇做法:
template<class T>void read(T &x)
{
x=0;int f=0;char ch=getchar();//f表示正负性,所以这个可以读入负数
while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return;
}
其中,template是定义模板的方法。我们可以用它来定义一个函数模板,譬如上面的代码。
这样一来,我们可以使用它读入int、long long等类型,它就会自动把T替换成int、long long。
读入实数就复杂一点,要判断小数点。
输出优化
在个别输出巨多的题中,使用输出优化也可以优化很多。
下面是用递归实现的输出优化:
inline void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
-O2
-O2和下面要说的-O3都是比赛时不能用的(毕竟要考虑到pascal选手的心情),不过平常可以用一用,娱乐娱乐。用法主要下面两项:
- 被卡常,悠哉悠哉地贴个-O2就过了;
- 打暴力,加个-O2,可以梦想多骗点分。
目前我看到的-O2有两种开法,第一种放在程序开头:
#pragma GCC optimize(2)
第二种放在每个函数(包括主函数)前面:
__attribute__((optimize("-O2")))
据说它内部的实现是打开了很多个优化开关(当然具体原理我也不懂),所以就能让你的程序起飞。
-O3
-O3是-O2的升级版,所以大部分时间它能优化得更快。不过它不大稳定,有时比-O2慢好多,有时甚至开了跟没开一样。
亦是放在每个函数前面:
__attribute__((optimize("-O3")))