部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

编程之美--2.21只考加法的面试题

问题1: 写一个程序,对于一个64位正整数,输出它所有可能的连续自然数(两个以上)之和的算式。

解:利用等差数列的计算公式

这里公差d=1,因此
Sn = n*a1 + n*(n-1)/2 
已知Sn如果能确定a1或n的一个,那么序列也就确定了。
假设这个正整数n可以表示成2个以上的连续自然数之和,那么可以设这个序列为a,a+1....a+n-1。
那么Sn=a+(a+1)+...+(a+n-1)=n*a + n*(n-1)/2 
通过遍历n来求a,如果a为整数,则符合要求。
因此首先要确定n的边界(最大值)。

n^2+(2*a1-1)*n-2*Sn=0 可得
n1= (1-2*a1+sqrt((2*a1-1)^2+4*2*Sn))/2
n2= (1-2*a1-sqrt((2*a1-1)^2+4*2*Sn))/2
a1=0时 n1为n的最大值,这个值令其为n_max
所以比较方法为:i=1到n_max, 根据公式计算a,如果a为整数,那么满足要求。

代码:

public static void GetPlusSeq(long Sn){
    long n_max =(long) (1+Math.pow(1+8*Sn,0.5))/2;
    //System.out.println("n的最大值为:"+n_max);
    long a ;
    for(long i = 1 ; i <= n_max ; i++){
        long fenmu = 2*Sn-i*i+i;
        long fenzi = 2*i;
        if(fenmu%fenzi==0){//分母可以被分子整除,证明a为整数
            a = fenmu/fenzi;
            if(a==0|a==Sn) //要求分子不为0,且至少为两个数相加(a=Sn则只有一个数) 
                continue;
            System.out.print(Sn +" = sum " );
            for(long k = 0 ; k < i ; k++){
                System.out.print(a+k+"  ");
            }
            System.out.println();
        }
    }
}

main函数内代码

long Sn = 10000;
GetPlusSeq(Sn);

结果:

10000 = sum 1998 1999 2000 2001 2002
10000 = sum 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
10000 = sum 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
10000 = sum 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142

 

问题2:一些数字不能表达为一系列连续的自然数之和,这样的数字有什么特点?

参考:http://blog.csdn.net/huahuahailang/article/details/8803939 

解题思路:
因为num=(2*i+k-1)*k/2
接下来分析(2*i + k-1)*k*(1/2)的特征。
2*i为偶数。若k为奇数,k-1为偶数。则(2*i + k-1)*(1/2) 是一个整数。设为X。则num=k * X =奇数 * X .
2*i为偶数。若k为偶数,k-1为奇数。则(2*i + k-1)为奇数。则 k*(1/2) 是一个整数。设为X。则num=(2*i + k-1) * X =奇数 * X .
由此可见,num的因式分解中必须含有一个奇数才可以表达成连续自然数相加的形式。

问题3:在64位正整数范围内,子序列数目最多的数是哪一个?

(题意是问子序列中有的数字数目最多的是那个数)

解:子序列从1开始向后加可以形成最长的序列。设这个序列的和为X,则在64位正整数范围内,X<2^64-1

X=1+2+3+...+K = K*(K+1)/2<x^64-1

解出k <=6074000999 则num= 18446744070963499500

 

posted @ 2015-06-23 19:41  流了个火  阅读(167)  评论(0)    收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats