如何查找多维数据集以特定数字结尾的数字?

时间:2013-10-19 18:28:03

标签: c++

给出数字N以1,3,7或9结尾。

总会存在一个数字M,当立方体以相同的原始数字N结束时,M不需要比N更多的数字。

示例: - N = 123。 M = 947。 (947)^ 3 = 849278123。这里(947)^ 3以N结尾(其为123)。

编写一个以N为输入并找到M的程序,其中M是与N相同的位数,当立方结束于N时。

我把代码编写为:

#include "iostream"
#include "math.h"
using namespace std;

int main()
{
    long long int t,p,j,i,d,c,s;
    cin>>t;
    long long int *n= new long long int[t];
    for(i=0;i<t;i++)
    {
        cin>>n[i];
    }
    for(i=0;i<t;i++)
    {   d=0; j=1;
        p=n[i];
        while(p)
        {
            d++;
            p=p/10;

        } p=n[i];
        s= pow(10,d);
        while(1)
        {
            c=j*j*j;
            if(c%s==p){break;}
            j++;

        }
    cout<<j<<endl;
     }
    return 0;
}

时限为1秒。时限超过1。

3 个答案:

答案 0 :(得分:4)

你可以做很多事情。首先 - 注意以奇数结尾的立方体必须以奇数开始 - 所以只能在时间节省中尝试M因子2的奇数。

下一步 - 要查找数字的最后3位数,只需执行number % 1000。并且不要使用pow。这很慢。看看我找到数字大小的技巧。

你最终得到这样的东西:

long int N, M, div;

printf("what is the value of N?\n");
scanf("%d", &N);
// test that it is reasonable before continuing...
// I did not write that code, but you should (size of N, and does it end in 1, 3, 7, or 9?

// find out how many digits N has:
div = 1;
while(N / div > 0) {
  div *= 10;
}

// now loop around odd M
for(M = 1; M < div; M+=2) {
  if( (M*M*M)%d==N) break;
}
// when you come out of this loop, M is the number you were looking for.

最后一次调整 - 看看数字的立方体。

1*1*1 = 1
3*3*3 = 27

7*7*7 = 343
9*9*9 = 729

从此可以得出结论,如果N1结束,则只能检查以1结尾的数字:

for(M=1; M<div; M+=10) {

类似于其他值(3 - 从M = 7开始; 7 - 从M = 3开始; 9 - 从M = 9开始)。现在我们的代码速度提高了10倍......

可能不足以赢得比赛,但它应该有所帮助......

编辑刚刚运行了以下代码,它在0.02秒内给出了相同的答案(经过10,000次绕过算法) - 大约20微秒才找到M一次.. 。 注意 - 更新的m1数组,因此代码应该适用于以5结尾的“有效”数字(尽管不能保证数字将存在 - 并明确询问有关以1,3结尾的数字的问题,7和9)。

#include <stdio.h>
#include <time.h>

int main(void) {
    long long int N, M, div;
    long long int m1[] = {0, 1, 0, 7, 0, 5, 0, 3, 0, 9};
    time_t start, end;
    int ii;
    printf("what is the value of N?\n");
    scanf("%lld", &N);
    // test that it is reasonable before continuing...
    // I will leave that for you to do

    start = clock();
    // now starts the main loop
    // I go around it 10,000 times to get a "reasonable accuracy" since the clock()
    // function is not very granular (it was giving me "elapsed time zero")
    // obviously for competition you want to do this just once!
    for (ii = 0; ii < 10000; ii++) {
      // find out how many digits N has:
      div = 1;
      while(N / div > 0) {
        div *= 10;
      }

      // now try possible values of M - given the last digit of N
      // we know what the last digit of M should be
      // so we can start with that number, then take steps of 10
      for(M = m1[N % 10]; M < div; M+=10) {
        if( ( M * M * M ) % div == N ) break;
      }

    } // do it 10,000 times to get some time on the clock

   // when you come out of this loop, M is the number you were looking for.
   // since the loop stops at div, it should never be larger than N
    printf("M is now %lld\n", M);

    printf("M cubed is %lld which ends in %lld\n", M * M * M, ( M * M * M ) % div);

    end = clock();

    printf("Time taken: %f sec\n", ((float)(end - start) ) / CLOCKS_PER_SEC);
}

答案 1 :(得分:1)

蛮力方法 - 循环所有可能性。应用数学可能围绕这个运行圈子,但是现在我让Applied Logic统治。找到答案 10,000次需要0.021337秒;运行它一次需要0.000004秒,这是非常慷慨的舍入。

通过奖励,它似乎也适用于以'5'结尾的值。

(编辑)Applied Logic建议您不必检查M&gt; 1000.毕竟,(1000 + M)³=1000³+ 3 *M²* 1000 + 3 * M *1000²+M³,由于我们使用mod,1000以上的所有内容都被取消,计算减少到M³ - 我想知道,也许我们应该将这个问题转移到math.stackexchange.com。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>

int main(int argc, char **argv)
{
    long long int N, M, val;
    int ii;
    time_t start, end;

    if (argc == 2)
        N = strtoul (argv[1], NULL, 10);
    else
    {
        printf("what is the value of N?\n");
        scanf("%lld", &N);
    }

    if (~N & 1)
    {
        printf ("invalid input\n");
        return EINVAL;
    }

    start = clock();
    for (ii=0; ii<10000; ii++)
    {
    for (M=1; M<1000; M+=2)
    {
        val = M%1000;
        val = val*val*val;
        if ((val % 1000) == N)
            break;
    }
    }
    end = clock();

    printf("For N=%lld, M=%lld, cubed is %lld which ends in %lld\n", N, M, M*M*M, (M*M*M)%1000);

    printf("Time taken: %f sec for 10,000 loops\n", ((float)(end - start) ) / CLOCKS_PER_SEC);

    return 0;
}

答案 2 :(得分:0)

让我们取数字N并重复计算其第三次幂(模数1000):

N0 = N
N1 = N0^3 mod 1000
N2 = N1^3 mod 1000
N3 = N2^3 mod 1000
...

如果N = 123,那么N19 = 947似乎很容易计算立方根。有可能证明这个程序会给我们一个答案(Stack Overflow站点不适合证明,所以请相信我或者问Math Overflow)。这个过程比其他任何过程都要快,但它似乎足够快;据我所知,它应该比蛮力方法更快,并有许多改进。

一些代码(基于原始代码):

while(1)
{
    c = j * j * j % s;
    if (c == p)
       break;
    j = c;
}

注意:这假设计算j * j * j不会溢出(小于2 ^ 63)。这对于最多6位数的N来说已经足够了,这可能是也可能不够好。