给出数字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。
答案 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
从此可以得出结论,如果N
在1
结束,则只能检查以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
来说已经足够了,这可能是也可能不够好。