【问题标题】:How does this piece of code function as fast i/o? [closed]这段代码是如何实现快速 i/o 的? [关闭]
【发布时间】:2015-07-29 15:05:59
【问题描述】:

我无法理解这个函数如何在 c++ 中导致更快的 i/o。 请帮帮我!

#include <iostream>
#include <cstring>

#define FOR(A,B,C) for(int A=B;A<C;A++)
#define EFOR(A,B,C) for(int A=B;A<=C;A++)
#define RFOR(A,B,C) for(int A=B;A>=C;A--)

using namespace std;

inline void Input(int &N)
{
int ch;
N=0;

while((ch<'0'||ch>'9')&&ch!='-'&&ch!=EOF)
    ch=getchar();

do
    N=(N<<3)+(N<<1)+(ch-'0');
while( (ch=getchar())>='0' && ch<='9');

return;
}

int main()
{
unsigned int fn[100005],gn[100005];
fn[0]=1,gn[0]=1,fn[1]=1,gn[1]=0;
int MOD=100000;

EFOR(fill,2,100001){
    fn[fill]=(fn[fill-1]+fn[fill-2]+2*gn[fill-1])%MOD;
    gn[fill]=(fn[fill-2]+gn[fill-1])%MOD;
}

int T;
Input(T);
while(T--){
    int N;
    Input(N);
    printf("%u\n",fn[N]%10000);
}

return 0;
}

没有该内联函数的这段代码正在获得 TLE,但有了它,它正在获得 AC 如果我只使用 cin 或 scanf 来获取输入,我会得到一个 TLE

【问题讨论】:

  • 比什么更快?
  • 您的代码有未定义的行为。 ch 永远不会在其初始比较之前在该 while 条件中建立一个值。
  • 什么是 TLE 和 AC? (我想我知道,但我不应该问)。你用这个软件玩什么游戏?一些在线编程挑战网站?
  • 这段代码混合了糟糕的编程风格和毫无意义的优化尝试。它不是“快速 i/o”。

标签: c++ io


【解决方案1】:

假设第一行是:int ch = getchar();

while((ch<'0'||ch>'9')&&ch!='-'&&ch!=EOF)
    ch=getchar();

这些行跳过所有不是数字的字符。虽然你应该正确使用-

(N&lt;&lt;3)+(N&lt;&lt;1) 等价于N * 8 + N * 2N * 10

(ch-'0') 会将字符 ch 从可打印字符转换为数字。

添加到先前的结果10 * N 会将新读取的字符附加到 N。

它可能比使用cinprintf("%d", &amp;N) 的格式化输入更快,原因如下:

  • 读取原始输入而不是格式化。
  • 使用移位的乘法

【讨论】:

  • 感谢您的回答!!。您能解释一下您应该正确使用“-”是什么意思吗??
  • 乘以编译时常量,替换为移位加法更有可能减慢代码速度,而不是加快代码速度。现代平台提供了比移位加法更好的编译时乘法选项10。在这种情况下,唯一的希望是编译器足够聪明,可以将这些转换反向工程为乘以 10,然后正确地重新实现它。
  • @AnT 这些是人们在经过大量剖析后在竞争性编程中使用的一些方法。不用说 OP 已经搞砸了代码。尽管我很少使用它,但当测试用例中的输入/输出很密集时,这些技巧有时会很有帮助。在客户的生产代码中,这样的成本几乎是不必要的。
  • 这样的技巧在某些非常特殊的情况下可能很有用。编译时乘以 10 不是其中之一。在“竞争性编程”中使用它的人要么感到困惑,要么将其作为其标志性风格的一部分。没有合理的理由这样做。
  • @AnT 完全同意你的看法。大多用-O2,就不用写难看的代码了。
【解决方案2】:

代码会跳过所有非数字字符,然后读取所有数字并将它们累积成一个数字。

N=(N<<3)+(N<<1)+(ch-'0');

是对

的优化
N = N*10+(ch-'0')

这在大多数编译器/平台上是完全不必要的。

错误和可移植性问题:

  • ch 未初始化
  • 输入“-”以 N=0 结束输入。这可能不是故意的

【讨论】:

  • 即使在 EBCDIC 0-9 中也是连续的。此外,C 规范保证这些是连续的。 a-z 可能是连续的,也可能不是连续的。
  • 谢谢@MohitJain。删除它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-12
  • 2017-01-12
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
  • 2011-12-08
  • 1970-01-01
相关资源
最近更新 更多