座右铭是找到N以下3或5的所有倍数之和。
这是我的代码:
public class Solution
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int t = in.nextInt();
long n=0;
long sum=0;
for(int a0 = 0; a0 < t; a0++)
{
n = in.nextInt();
sum=0;
for(long i=1;i<n;i++)
{
if(i%3==0 || i%5==0)
sum = sum + i;
}
System.out.println(sum);
}
}
}
对于某些测试用例,执行时间超过1秒。谁能帮助我,以减少时间的复杂性?
答案 0 :(得分:1)
我们可以找到低于d
的{{1}}的所有倍数的总和,作为算术级数的总和(它们的总和等于N
)。
d + 2*d + 3*d + ...
然后结果将等于:
long multiplesSum(long N, long d) {
long highestMultiple = (N-1) / d * d;
long numberOfMultiples = highestMultiple / d;
return (d + highestMultiple) * numberOfMultiples / 2;
}
我们需要减去long resultSum(long N) {
return multiplesSum(N, 3) + multiplesSum(N, 5) - multiplesSum(N, 3*5);
}
,因为有些数字是multiplesSum(N, 15)
和3
的倍数,我们将它们加了两次。
复杂性: O(1)
答案 1 :(得分:0)
在这种情况下,您无法减少时间复杂度,因为每组数字仍有O(N)
。但是,您可以使用整数除法来减少常数乘数:
static int findMultiples(int N, int s)
{
int c = N / s, sum = 0;
for (int i = 0, k = s; i < c; i++, k += s)
sum += k;
return sum;
}
这样你只能循环遍历倍数而不是整个范围[0,N]。
请注意,您需要执行findMultiples(N, 3) + findMultiples(N, 5) - findMultiples(N, 15)
,以删除3和5的重复倍数。因此,循环次数为N / 3 + N / 5 + N / 15 = 0.6N而不是N
编辑:一般来说,任意数量的除数的解是sum(findMultiples(N,divisor_i) - findMultiples(N,LCM(all_divisors))
;但是,如果sum(1/divisor_i) + 1/LCM(all_divisors) < 1
只是值得这样做,否则会有更多的循环。幸运的是,对于2个除数,这永远不会成真。
答案 2 :(得分:0)
从1到(包括)N的所有数字的总和已知为N(N + 1)/ 2(不需要迭代)。
因此,从K到KM的所有K的倍数之和是上述公式的K倍,得到KM(M + 1)/ 2.
将它与@meowgoesthedog的findMultiples(N,3)+ findMultiples(N,5) - findMultiples(N,15)想法相结合,你就有了一个恒定时间的解决方案。
答案 3 :(得分:-1)
解决问题的方法。解决问题的最快方法。
import java.util.*;
class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
while(t!=0)
{
long a=in.nextLong();
long q=a-1;
long aa=q/3;
long bb=q/5;
long cc=q/15;
long aaa=((aa*(aa+1))/2)*3;
long bbb=((bb*(bb+1))/2)*5;
long ccc=((cc*(cc+1))/2)*15;
System.out.println(aaa+bbb-ccc);
t-=1;}
}
}