减少大量计算的运行时间

时间:2015-02-20 13:06:49

标签: c++ algorithm

沿着Waa放大是一个由SKIT数学系组织的简单游戏。游戏的目标是按正在递增的顺序说正整数,有一个转折点:你没有说可以被3和5整除的数字。相反,每当一个数字可以被3整除时,你会说“缩放”并且数字可以被整除5你说“waa”。 (因此,如果一个数字可以被15整除,你会说“zoomwaa”。)

以下是游戏的开始方式:

1, 2, zoom, 4, waa, zoom, 7, 8, zoom, waa, 11, zoom, 13, 14, zoomwaa,  
16, 17, zoom, 19, waa, zoom, 22, 23, zoom, waa, 26, zoom, 28, 29,  
zoomwaa, 31, 32, zoom, 34, waa, zoom, ...

放大Waa也成为SKIT CS学生的传统编程问题。但是,在这个问题上,我们有一个更棘手的任务。

给予长A和B.考虑游戏中与A到B的整数对应的部分。在这部分游戏中,你会说“缩放”X次,“waa”Y次,“zoomwaa”Z次。你必须确定X,Y和Z。

输入:

第一行输入包含一个整数T,表示测试用例的数量。每个测试用例都有一行输入,包含两个空格分隔的整数,A和B.

输出

在每个测试用例的空格分隔上打印X,Y和Z的值。

约束:

1< = A< = 10 ^ 18
A< = B< = 10 ^ 18
1< = T< = 4左

示例输入(明文链接)

4
1 4
2 6 
150 165 
474747 747474

示例输出(明文链接)

1 0 0
2 1 0
4 2 2
72728 36363 18182

我的代码如下所示

#include<iostream>
using namespace std;
int main()
{
long long num[2];
int t,i,j,ii,jj,kk;
//--t is number of test inputs--//
cin>>t;
for(i=0;i<t;i++)
{
    <!--ii increments if number is divisible by 3 i.e., number is Zoom--
      --jj increments if number is divisible by 5 i.e., number is Waa--
      --kk increments if number is divisible by 15 i.e., number is Zoom-- 
    ii=0;jj=0;kk=0;
    for(j=0;j<2;j++)
    {
        cin>>num[j];
    }
    while(num[0]<=num[1])
    {
        if(num[0]%3==0 && num[0]%15!=0)
        ii++;
        if(num[0]%5==0 && num[0]%15!=0)
        jj++;
        if(num[0]%15==0)
        kk++;
        num[0]++;
    }
    cout<<ii<<" "<<jj<<" "<<kk<<endl;
}
cin>>t;
}

此代码对给定的示例输出有效 它不适用于以下给定的输入,即, 示例输入

3
1 961574729077486878
1 969690745985575352
2 932572744790738365

示例输出

256419927753996501 128209963876998250 64104981938499125
258584198929486760 129292099464743380 64646049732371690
248686065277530231 124343032638765116 62171516319382557

请指定合适的算法以减少程序的运行时间...从那以后     while循环在计算中花费了很多时间。

3 个答案:

答案 0 :(得分:2)

你不应该迭代给定的范围,因为这太慢了。

让我们解决一个处理范围[1, x]的简单问题:

在此范围内,有:

x / 3 numbers divisible by 3
x / 5 numbers divisible by 5
x / 15 numbers divisible by 15

现在你希望那些可被3整除,但不能被15整除,5而不是1515,你也想要推广它到范围[a, b]。你应该可以从这里做到这一点。

答案 1 :(得分:2)

这里有一个数学捷径。您可以使用离散数学中的包含 - 排除原则来确定X,Y和Z的值。例如,让我们使用范围[10,100]来完成概念。

对于3:10/3 = 3和100/3 = 33.对于5:10/5 = 2和100/5 = 20.对于15:10/15 = 0和100/15 = 6。

请注意,您必须始终向下舍入整数。

现在,33-3 = 30,20-2 = 18,6和0 = 6.您知道Z的值为6,因为此范围内有6个数字可被15整除。但是, Y的值不是18.你必须考虑15可以被5整除,所以你需要减去数字Z. 18 - Z(6)= 12.同样适用于寻找X. 33 - Z(6 )= 27.因此,对于这个例子,答案是X = 27,Y = 12,Z = 6.

作为一般情况,以下是您需要做的事情:

将每个因子(3,5和15)除以范围的下限并保存这些值,始终向下舍入到最接近的整数。然后将每个因子除以范围的上限,再次向下舍入到最接近的整数。减去这些值以获得可被这些数字整除的范围内的数字量。然后记住一些数字正在计数两次,从zoom和bah中减去zoombah的值。这将为您提供正确的答案。

编辑:在查看其他答案后,我意识到您还必须检查以确保您的下限不能完全被因子整除。如果是这种情况,那么你必须在你的“在范围内被X整除的数字的数量”中加1。

答案 2 :(得分:1)

x

可以找到n/x从1到n整除的元素数量

通过

查找从ab(包括)可被3整除的元素数量
b/3 - a/3

但如果a可以被整除3,那么你会少一个。所以将a减少1

a1=b/3 - (a-1)/3;
a2=b/5 - (a-1)/5;
a3=b/15 - (a-1)/15;


// To remove numbers divisible by 3 and 15
a1=a1-a3;
// To remove numbers divisible by 5 and 15
a2=a2-a3;
cout<<a1<<" "<<a2<<" "<<a3<<endl;
相关问题