[英]Making linear search more efficient
我有 3 个灯泡的问题,它们以不同的速率打开,并被告知找到并计算它们同时打开的时间(基于给定的时间范围)。 示例:1 2 3 1 20(1 是开始时间,20 是结束时间)将是 output 36. (6 + 12 + 18)。 下面的代码有效,但它可能会更快。 我怎样才能做得更好? 谢谢你的帮忙。
long long int total = 0, time1 = 0, time2 = 0, time3 = 0, start = 0, end = 0;
scanf("%lli %lli %lli %lli %lli", &time1, &time2, &time3, &start, &end);
for(int j = start; j <= end; j++)
{
if(j % time1 == 0 && j % time2 == 0 && j % time3 == 0)
{
total = total + j;
}
}
printf("Case #%i: %lli\n", testcase, total);
与许多算法问题一样,有一个数学观察可以大大加快您的代码速度。 对于要被所有 3 个灯泡整除的时间,时间必须能被它们的最小公倍数整除。 因此,您会得到一个必须在开始和结束之间检查的固定时间间隔。 这也可以用另一个公式来完成。
该问题可以分解为以下步骤:
导通时间的最小公倍数 LCM可以通过首先找到导通时间的最大公约数GCD和导通时间的乘积P来找到,然后LCM = P / GCD 。 著名的欧几里德算法可以用来求一对数的最大公约数,并且可以多次使用该算法来确定整体的最大公约数。
以上步骤由下面的function get_total
实现。
unsigned long long int gcd(unsigned long long int a, unsigned long long int b)
{
while (b) {
unsigned long long int t = b;
b = a % b;
a = t;
}
return a;
}
unsigned long long int
get_total(unsigned long long int start, unsigned long long int end,
unsigned int ntimes, const unsigned long long int *times)
{
unsigned long long int g; /* GCD of times */
unsigned long long int l; /* LCM of times */
unsigned long long int first, last;
unsigned long long int n;
unsigned long long int total;
if (ntimes == 0 || times[0] == 0)
return 0; /* error */
/* Calculate GCD and LCM of times. */
g = times[0];
l = 1;
for (unsigned int i = 1; i < ntimes; i++) {
if (times[i] == 0)
return 0; /* error */
g = gcd(times[i], g);
l *= times[i];
}
l *= times[0] / g;
/* Get the first and last occurrences of multiples of LCM in range. */
first = ((start + (l - 1)) / l) * l; /* round up */
last = end - (end % l); /* round down */
if (first > last)
return 0;
/* Get number of occurrences of multiples of LCM in range. */
n = ((last - first) / l) + 1;
/* Get sum of arithmetic progression of multiples of LCM in range. */
total = (n * (first + last)) / 2;
return total;
}
ntimes
是times指向的数组中灯泡点亮的times
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.