如何减少执行时间
Posted
技术标签:
【中文标题】如何减少执行时间【英文标题】:how to reduce execution time 【发布时间】:2013-10-01 15:52:27 【问题描述】:目前,对于hackerearth.com 上提供的某些测试用例,以下问题需要 3.008** 秒才能执行,其中允许的时间为 3.0 秒,因此出现时间限制错误。请帮助减少执行时间。
问题: Alice 刚刚学会了将两个整数相乘。他想将两个整数 X 和 Y 相乘以形成一个数 Z。为了使问题变得有趣,他将选择 [1,M] 范围内的 X 和 [1,N] 范围内的 Y。帮助他找到他可以通过哪些方式做到这一点。
输入
输入的第一行是测试用例的数量 T。接下来是 T 行。每行有三个空格分隔的整数,数字 Z、M 和 N。
输出
为每个测试用例输出一个整数,表示方法的数量。
约束 1
代码:
#include <iostream>
using namespace std;
int chk_div(long long a,long long b)
if(((a/b) * (b) )==a)return 1;
return 0;
int main()
int t;
long i,j,count;
long n,m,z;
cin>>t;
while(t--)
count=0;
cin>>z>>m>>n;
if(m>z)m=z;
if(n>z)n=z;
if (m>n)m=n;
for(i=1;i<=m;i++)
if(chk_div(z,i))count++;
cout<<count<<"\n";
return 0;
【问题讨论】:
爱丽丝是一个女孩的名字。((a/b) * (b) )==a
-> a % b == 0
(尽管编译器可能已经为你优化了这个)。另外,只是样式问题,但更喜欢使用min
进行比较,您的代码将更具可读性。
仅供参考,消除空白并不能让它运行得更快。
爱丽丝库珀???
好的,只是为了解决实际问题,这里有一个很大的提示:en.wikipedia.org/wiki/Integer_factorization
【参考方案1】:
这里的主要性能问题是您的内部循环执行 10^12
迭代的事实。你可以把它减少一百万次到sqrt(z) <= 10^6
。
这里的诀窍是要注意,Alice 可以写z = x * y
当且仅当他可以写z = y * x
。另外,x <= sqrt(z)
或 y <= sqrt(z)
。使用这些事实,您最多只能迭代 z
的平方根来计算所有案例。
【讨论】:
【参考方案2】:我相信这应该可以完成工作(来自@zch 的回答):
#include <iostream>
#include <cmath>
auto MAX = [] (int A, int B) -> bool return A > B ? A : B; ;
auto MIN = [] (int A, int B) -> bool return A < B ? A : B; ;
using std::cout;
using std::cin;
int main()
long long Z, M, N, T, low, high, temp, div;
int ans;
for (cin >> T; T--; )
cin >> Z >> M >> N;
temp = MIN(M, N);
low = MIN(sqrt(Z), temp);
high = MAX(M, N);
for( ans = 0; low > 0 && (Z / low) <= high; --low )
if ( Z % low == 0)
++ans;
div = Z / low;
ans += (div != low && div <= temp);
//cout << temp << " * " << Z / temp << " = " << Z << "\n";
cout << ans << "\n";
return 0;
稍后会添加 cmets
使用 cmets 编写代码:
#include <iostream>
#include <cmath>
auto MAX = [] (int A, int B) -> bool return A > B ? A : B; ;
auto MIN = [] (int A, int B) -> bool return A < B ? A : B; ;
using std::cout;
using std::cin;
int main()
long long Z, M, N, T, low, high, temp, div;
int ans;
for (cin >> T; T--; )
cin >> Z >> M >> N;
temp = MIN(M, N);
low = MIN(sqrt(Z), temp);//Lowest value <--We start iteration from this number
high = MAX(M, N); //Maximum value
for( ans = 0; low > 0 && (Z / low) <= high; --low )
//Number of things going on in this for-loop
//I will start by explaining the condition:
//We want to keep iterating until either low is below 1
// or when the expression (Z / low) > high.
//Notice that as the value of low approaches 0,
//the expression (Z / low) approaches inf
if ( Z % low == 0)
//If this condition evaluates to true, we know 2 things:
/*Z is divisible by this value of low and
low is in the range of MIN(M,N) <--true*/
/*Because of our condition, (Z / low) is
within the range of MAX(M, N) <--true*/
++ans;
div = Z / low;
//This second part checks if the opposite is true i.e.
/*the value of low is in the range of
MAX(M, N) <--true*/
/*the value (Z / low) is in the range of
MIN(M, N) <--true only in some cases*/
ans += (div != low && div <= temp);
//(div != low) is to avoid double counting
/*An example of this is when Z, M, N have the values:
1000000, 1000000, 1000000
The value of low at the start is 1000 */
cout << ans << "\n";
return 0;
【讨论】:
一个好的开始。提高速度的下一步可能是考虑 Z。 @Smac89 感谢代码工作......但你不能解释一下“ans += (div != low && div @MahendraChandwani 以下是代码在使用 Z = 1000000、M = 1000000、N = 1000000 的值运行时生成的values。从示例中可以看出,生成的第一个输出是1000 * 1000
。这就是说 X 的值为 1000 而 Y 的值为 1000 来生产产品 Z。现在如果我要交换 X 和 Y 的值,这是多余的,因为 X 仍然是 1000 而 Y 仍然是 1000。所以没有必要多次计算这种情况,因为我们没有得到不同的 X 和 Y 值
@MahendraChandwani 为了最大化我们获得的组合数量,我们尝试查看一些较高的最终值是否也可以放入较小的存储桶中。这就是为什么我们这样做div <= temp
。随着迭代的继续 div 变得越来越大,这样做,我们能够在它变大之前获得尽可能多的匹配。请注意,这行简单的代码 ans += (div != low && div <= temp);
使我们不必利用我们已经获得的值进行两次迭代。【参考方案3】:
事实上,你必须以不同的方式解决问题:
求素数分解:
所以Z = A^a * B^b * ... * P^p
和A, B, .., P
素数
所以你只需要计算来自a, b, ... p
的可能性数量。
(因此结果取决于 M&N 约束,最高可达 (1 + a) * (1 + b) * ... * (1 + p)
)。
【讨论】:
您还必须限制 M 和 N 指定的可能性。 @EricPostpischil:根据给定的约束,结果是max(M) == max(N) == Z
。
问题陈述表明 Z、M 和 N 从输入中读取为单独的整数。 M 和 N 可能小于或大于 Z。唯一的限制是 Z、M 和 N 中的每一个都至少为 1,并且最多为 10**12。
修正后,这对解决问题有何帮助?
@zch:对于大多数 Z 值,分解 Z 极大地减少了必须测试的案例数量。【参考方案4】:
你的 if(((a/b) * (b) ) == a) 返回 1;将始终返回 1。为什么要将 A 与 B (a/b) 相除,然后将结果乘以 B。这是模棱两可的,因为当您说 (a/b) * (b) 时,您的答案将是 A。 B`s 会互相抵消,你只剩下 A 作为你的答案。所以基本上你是在比较 A == A,这是真的。
【讨论】:
/
对于整数类型是整数除法,丢弃余数。例如9 / 4 == 2
.
重点是您将 A 除以 B,然后将结果与 B 相乘。我不确定 Double 是否受到限制或不应该在此问题中用于准确性目的。我认为这是留给编码人员的。
(9 / 4) * 4
将提供2 * 4 != 9
。这个检查是正确的,不过最好写成a % b == 0
。
如果是这种情况,我建议使用 mod 公式。即使这可能对性能问题没有帮助。但它可能会更快。我确信您可以使用 mod 公式的一行指令来完成,这与需要两行指令的计算不同。
他也可以试试 ((a/b) * (b) == a) ? 1:0;就限制指令总数而言。以上是关于如何减少执行时间的主要内容,如果未能解决你的问题,请参考以下文章