【问题标题】:Program exceeds a time limit, which seems impossible - buggy code程序超过时间限制,这似乎是不可能的 - 错误代码
【发布时间】:2012-04-02 21:04:53
【问题描述】:

这与数学有关,但我在这里发布我的代码,因为似乎有我无法理解的错误。

问题

两个机器人 AB 站在无限长的直线上的0 位置。机器人 A 可以向左或向右移动 ab 个单位,机器人 B 也可以相同,但使用 cd 单位。他们将按下位于该直线上的按钮,距离0 不超过 k 个单位。您可以在pi 的多少个位置上放置按钮,以便两个机器人能够相互独立地按下它(实际上到达它)。所以输入是 1 行中的 5 个正整数:abcd k

约束:0a,b,c,d,k1018 和数量测试用例 t 其中 1t1000

时间限制:1 秒

例如:机器人 A (a = 1, b = 2),机器人 B (c = 4,d = 5),范围:k = 1

本例的答案是3

我想一个解释会使这个问题不必要地冗长并偏离主要关注点。我正在给出我想出的解决方案并继续我的代码。

我的解决方案:

m = LCM ( HCF(a, b) , HCF(c, d))

答案 = 2 * [k / m] + 1

[ ] 表示最大整数函数(只是为了避免混淆)。

简短地说(对于那些对此问题感兴趣的人),我所做的就是检查 k 范围内存在多少个 m两边加上 0 位置。 HCF(a,b) 将给出机器人可以采取的最短步骤,LCM 将给出它们可以站立的最小共同位置。然后找到号码。倍数。

代码(C++):

  1 #include <cstdio>
  3 using namespace std;
  4 typedef long long LL;
  5 
  6 inline void swap(LL *a, LL *b)
  7 {
  8     *a ^= *b;
  9     *b ^= *a;
 10     *a ^= *b;
 11 }
 12 
 13 long hcf(LL a, LL b)
 14 { return !a || !b ? a+b : hcf(b,a%b); }
 15 
 16 LL lcm(LL a, LL b)
 17 {
 18     if(a < b) swap(&a,&b);
 19     LL i=a;
 20     while(a%b) a+=i;
 21     return a;
 22 }
 23 
 24 int main()
 25 {
 26     int t; scanf("%d\n",&t);
 27     while(t--)
 28     {
 29         LL a,b,c,d,k;
 30         scanf("%lld %lld %lld %lld %lld",&a,&b,&c,&d,&k);
 31         printf("%lld\n", 1 + ((k / (lcm(hcf(a,b), hcf(c,d))) ) << 1) );
 32     }
 33     return 0;
 34 }

我只是简单地实现了我的答案。我还通过 1000 个测试用例执行了我的程序,每个测试用例由 [1016、1018] 范围内的随机 + 整数组成。我多次这样做,最坏情况下的时间消耗是 0.01 秒。

现在,当我将此代码提交到比赛页面时,我收到 Time Limit Exceeded 错误!这是不可能的,除非某些错误循环针对特定输入无休止地运行。我认为我应该听取专家对我的代码为什么会超时的意见。请帮忙

P.S.:如果您对这个问题有更好的答案,欢迎您:-)

编辑:P.S.:我对我在C++ 中处理大整数的方式持怀疑态度,因此我将其转换为python 并提交,这再次产生了Time Limit Exceeded错误。

【问题讨论】:

  • 您对 Stack Overflow 有什么问题?
  • 请参阅this question。你知道Jack吗?
  • 问题是,为什么代码会出现 Time Limit Exceeded 错误,也就是说,如何在被竞赛网站测试时超过 1 秒?解决方案非常简单。
  • 不要异或交换。此行返回 !a || !b? a+b : hcf(b,a%b);在语法上是模棱两可的,很可能被解释为 (!a) || (!b ? a+b : hfcf(b,a%)) 我收集的不是你的意图。交换函数的原型应为 void swap(LL& a, LL& b) ,然后您不需要将地址作为参数传递。在 scanf 和 printf 中使用如此长的表达式会使代码更难阅读。你能保证 scanf 正确地接受比赛中的输入吗?也许不是 argc/argv[]?
  • 嗯,不,我没有!我们的问题很相似,但他想知道如何解决。我已经解决了,我这里遇到了不同的问题

标签: c++ performance debugging infinite-loop


【解决方案1】:

您的代码中充满了从stdin 读取的scanf 调用。除非提供输入,否则它将无限期挂起。大多数比赛没有从stdin 读取您的代码。规则说什么是输入的来源?

【讨论】:

  • 输入来自使用 i/o 重定向器的输入文件。我已经以完全相同的方式尝试了针对输入的代码。
  • 输入文件由他们提供。我们无权访问这些文件。
  • 我做了一个python程序来生成一个输入文件。让我把它上传到某个地方,我会在这里发布链接
  • 好的,如果您的输入文件与他们的格式不匹配,那就可以解释问题了。
【解决方案2】:

注意这段代码非常危险:

inline void swap(LL *a, LL *b)
{
   /* sometimes also written as *a^=*b^=*a^=*b;  */
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}

如果 ab 曾经指向同一个内存,这将清零该内存。

(尝试使用此交换来反转具有奇数个字母的字符串)

char* input = "abcde"
for(i=0, j=4; i<3; ++i, --j)
{
    swap(input+i, input+j);
}
// Result:  "ed0ba".
// With a normal-swap, 'c' would get swapped with 'c', returning "edcba"

【讨论】:

  • 您是说 a 和 b 可以是“相同的数字”吗?这肯定会将它们归零,但在这里,如果 a & b 将仅在 a 时交换
  • 在这个特定的代码中,您受到“if (a
  • 是的!我现在总是很小心。以前有过问题。
  • 这是一种交换变量的可怕方式。它引入了风险,并没有提高速度。没有充分的理由像这样交换。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-28
  • 2014-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-20
  • 1970-01-01
相关资源
最近更新 更多