前言
打newcode和上海重现赛的时候两次遇到很类似的超时情况,特别是有道题特别提示了“请使用更高效的输入方式”,误导了我好久,,,,
众所周知标准化输入输出(scanf、printf)比输入输出流(cin、cout)要快,原因可以参见很多博文,这里选一篇
https://www.cnblogs.com/xienaoban/p/6798095.html
更快的是输入输出挂,原因是getchar()比scanf还要快,
于是有了如下公式:
输入速度:getchar > scanf > cin
验证一下
首先,随机产生一百万个整型数,写入指定文件里
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
srand(time(NULL));
freopen("00out.txt", "w", stdout);
int n;
int num = 1000000;
while(num--)
{
n = rand() % 1000;
cout << n << ' ';
}
return 0;
}
然后,分别用输入挂(getchar)、scanf、cin读入一百万个整型数字,看运行时间
#include <ctime>
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 1000005;
int a[N];
int b[N];
int Scan() ///输入外挂
{
int res = 0, ch ,flag = 0;
if( (ch = getchar()) == '-' )
flag = 1;
else if(ch >= '0' && ch <= '9')
res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9')
res = res * 10 + ch - '0';
return flag ? -res : res;
}
void Out(int a) ///输出外挂
{
if(a < 0)
{
putchar('-');
a *= -1;
}
if(a > 9)
Out(a / 10);
putchar(a % 10 + '0');
}
int main()
{
clock_t start, over;
double duration;
freopen("00out.txt", "r", stdin);
start = clock();
for(int i = 0; i < 1000000; ++i)
a[i] = Scan();
over = clock();
duration = double(over - start) / CLOCKS_PER_SEC;
cout << duration << " (s)" << '\n';
fclose(stdin);
freopen("00out.txt", "r", stdin);
start = clock();
for(int i = 0; i < 1000000; ++i)
scanf("%d", &a[i]);
over = clock();
duration = double(over - start) / CLOCKS_PER_SEC;
cout << duration << " (s)" << '\n';
fclose(stdin);
freopen("00out.txt", "r", stdin);
start = clock();
for(int i = 0; i < 1000000; ++i)
cin >> a[i];
over = clock();
duration = double(over - start) / CLOCKS_PER_SEC;
cout << duration << " (s)" << '\n';
fclose(stdin);
}
Then
嗯,,,所以输入挂很快(可惜一般很少用到,真正能凑巧用这个卡过去的不多)
输入输出挂模板
int Scan() ///输入外挂
{
int res = 0, ch ,flag = 0;
if( (ch = getchar()) == '-' )
flag = 1;
else if(ch >= '0' && ch <= '9')
res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9')
res = res * 10 + ch - '0';
return flag ? -res : res;
}
void Out(int a) ///输出外挂
{
if(a < 0)
{
putchar('-');
a *= -1;
}
if(a > 9)
Out(a / 10);
putchar(a % 10 + '0');
}
关于double的读入挂(更是用不到)
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
double Scan()
{
int ch, pos = 1, num = 0;///num为字符串总长度,pos为小数点排第几位
double res = 0;
bool flag = 0, found = 0;
if( (ch = getchar()) == '-' )
flag = 1;
else if(ch >= '0' && ch <= '9')
res = ch - '0';
num++;
while((ch = getchar()) >= '0' && ch <= '9' || ch == '.')
{
num++;
if(ch == '.')
{
found = 1;
pos++;
}
else
{
res = res * 10 + ch - '0';
if(!found)
pos++;
}
}
res *= pow(0.1, num - pos);
return flag ? -res : res ;
}
int main()
{
double ans;
while(ans = Scan())
{
cout << fixed << std::setprecision(10) << ans << '\n';
}
return 0;
}
注意事项
scanf("%d", &n);
getchar();
for(int i = 0; i < n; ++i)
a[i] = Scan();
中间的getchar()不加上可能输出测试时表面上看没影响,但做题会给你WA掉