目前,以下问题是在hackerearth.com上提供的某个测试用例执行3.008 **秒,允许时间为3.0秒,因此我得到时间限制错误。请帮助减少执行时间。
问题: 爱丽丝刚学会乘以两个整数。他想将两个整数X和Y相乘以形成数字Z.为了使问题变得有趣,他将在[1,M]范围内选择X,并在[1,N]范围内选择Y.帮助他找到数字他能做到这一点的方式。
输入
输入的第一行是测试用例T的数量。接下来是T行。每行有三个空格分隔的整数,数字Z,M和N.
输出
对于每个测试用例输出一个整数,方式的数量。
约束 1&lt; = T&lt; = 50 1&lt; = Z <= 10 ^ 12 1 <= M <= 10 ^ 12 1 <= N <= 10 ^ 12
CODE:
#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;
}
答案 0 :(得分:8)
此处性能的主要问题是内部循环执行约10^12
次迭代。你可以减少一百万次到sqrt(z) <= 10^6
。
这里的诀窍是注意到,当且仅当他能写z = x * y
时,Alice才能写z = y * x
。此外,还有x <= sqrt(z)
或y <= sqrt(z)
。使用这些事实,您只能迭代z
的平方根来计算所有情况。
答案 1 :(得分:5)
我相信这应该可以完成工作(来自@ 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;
}
将稍微添加评论
带注释的代码:
#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;
}
答案 2 :(得分:2)
事实上,您必须以不同的方式解决问题:
找到Prime分解:
Z = A^a * B^b * ... * P^p
A, B, .., P
素数
所以你只需要计算a, b, ... p
的可能性数量。
(因此结果最多为(1 + a) * (1 + b) * ... * (1 + p)
,具体取决于M&amp; N约束条件。)
答案 3 :(得分:-1)