编程之美读书笔记2.21—之考加法的面试题



解法1:时间复杂度降为O(sqrt(N))

      假设这个正整数n可以表示成2个以上的连续自然数之和,那么可以设这个序列为a,a+1....a+i。

       那么n=a+(a+1)+...+(a+i)=(i+1)*a + (i+1)*i/2。如果我们可以确定i的范围,那么我们就可以遍历i,对于所有的i的取值,得到对应的a的值,然后判断a是否为整数,即可知是否符合要求。

      这里i可以认为表示的是序列的长度,那么最长的序列必然是n=1+2...+i。所以有i*(i+1)=2n。

解得i=(sqrt(8n+1)-1)/2,所以i的取值就是[1, (sqrt(8n+1)-1)/2]区间中。

      随即,遍历i的取值,然后判断对应的a是否为整数即可。

#include<iostream>
#include <cmath>
using namespace std;
#define  ZERO  0.00001L

int main(int argc, char *argv[])
{
    long n=21, i, j, k;
    float temp, a;
   
    j = (sqrt((double)8*n+1) - 1) / 2;
    for(i=1; i<=j; i++)
    {
        temp = (n*1.0)/(i+1) - (1.0*i)/2;
        a = temp - (long)temp;
        if(a < ZERO && temp > ZERO)
        {
            cout<< n<<"="<<temp;
            for(k=1; k<=i; k++)
            {
               cout<<"+"<<temp+k;
            }
           cout<<endl;
        }
    }
	
	system("pause");
    return 0;

	
}
  
    3:
   由解答1可知,k的上界与N有关,N越大则k的取值范围越大,可能的序列数目就越多。
   因此,由贪心策略得,最大值MAX应具有如下形式
   MAX = 3^n
   由于是64位整数,有
   3^n < 2^64
  解得
   n < (ln2/ln3)*64 ,n是整数,n最大值是40
  所以有MAX = 3^40
    再由解答1得,序列数最多为20*2 = 40个


解法2:

对于正整数N,如果表示成2个连续自然数相加,N = m + (m + 1) = 2m + 1,则N为奇数;

如果表示成3个连续的自然数相加,N = (m - 1) + m + (m + 1) = 3m,则N为3的倍数;

如果表示成4个连续的自然数相加,N = (m - 1) + m + (m + 1) + (m + 2) = 2 * (2m + 1),则N为某奇数的2倍;

如果表示成5个连续的自然数相加,……,则N为5的倍数;

如果表示成5个连续的自然数相加,……,则N为某奇数的3倍;

……

已经找到规律了:对于N,

如果表示成偶数个(2 * k) 连续的自然数相加,      则N为k的倍数;

如果表示成奇数个(2 * k + 1)连续的自然数相加, 则N为(2 * k + 1)的倍数。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

void  printOut(__int64 M,int i,bool flag)   
{
	if(flag)
	{
		cout<<M/2<<" "<<M/2+1<<endl;
    }
	else
	{
		int mid=M/i; 
	    for(int j=mid-1;j<=mid+i/2;j++)
			cout<<j<<"  ";
		cout<<endl;
	}
}

void main()
{
	__int64  M;
	
	M=10;
	
        if(M%2==1)   //奇数
	       printOut(M,2,true);
	for(int i=3;i<=M/2;i=i+2)
	{
	       if(M%i==0)        //能被某个奇数整除
		   printOut(M,i,false);
	}

	
		 
	system("pause");
}

  2.

 从分析中可以看出,N的因式分解必然要有奇数。证明如下:

 a. 首先证明,只要N的因式分解中有奇数,N就能表示为自然数连和。

     如果N的因式分解中有奇数,假设为s,且N= k * s,

     如果k > s/2,

     则 N可以表示为这个序列的和:k - (s / 2), k - (s / 2) + 1 ... k + (s / 2);

     例如 54 = 6 x 9, 可表示为 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;(6 x 9,偶数为6,则6在这9个自然数的序列的中间)

     如果 k < s/2,

     则N可以表示为这个序列的和:(s + 1)/2 - k, (s+1)/2 - k + 1,..., (s + 1)/2 + k - 1;

     如54 = 2 x 27,则可表示为 12 + 13 + 14 + 15;(中间两个数 13 + 14 = 27)

 b. 再证明:如果N的因式分解中没有奇数,则N不能表示成连和的形式。 

     反证:如果能,假设N能表示成k个自然数的连和。

     如果k为偶数,设这k个数的中数(中间偏左的一个)为m,将这k个数收尾相加得到k/2个自然数的序列,

     易证这k/2个自然数都等于2m+1,

     那么N = (2m + 1) * k / 2,与N的因式分解中没有奇数矛盾;

 

     如果k为奇数,设中数为n,那么N = k * n,与N的因式分解中没有奇数矛盾。

     综上,得证。 

 


3.假设N的质因子分解中有k种奇数(不是k个)记为odd[1,..,k],odd[i]有n[i]个,那么N能表示的序列数为:


    Ns = (n[0] + 1) * (n[2] + 1) * (n[3] + 1) * ... * (n[k] + 1) - 1


 


验证:3*3*3*3*5*5*7*7*7 = 694575,我用程序打印,输出了59个。


这里有4个3,2个5,3个7,(4+1)*(2+1)*(3+1) - 1 = 60 - 1 = 59,验证成功。而694575乘以2的任意幂次方,所得结果都是59.


显然,拆分个数,只与奇质因子的数目有关。


2 ^ 64 = 1.8e19


3 * 5 *7 *11 *13 *17 * 19 *23 *29 *31 * 37 *41 * 43 *47 *53 = 1.6e19


 


假设N是有最多因子个数的最小64位奇数,设 N = 3^a3 * 5^a5 * 7^a7 …


则一定有 a3 >= a5 >= a7 … 否则只要交换不满足条件的那两个数,得到相同因子个数但比N更小的数,这与假设矛盾。


  S = 2 ^ 64 = 1.8e19


M=3*5*7*11*13*17*19*23*29*31*37*41*43*47*53=1.6e19(因子个数2^15)


因而,N的最大质因子一定小等于53


 


由S / (M / 53) = 60  可将60拆分成3^3(因子数5*2^13)  3^2 * 5(因子数3*2^14)


可得局部最优解:R1 = 3^3 *5^2 *7*11*13*17*19*23*29*31*37*41*43*47


如果N不等于R1,则a47 = 0(要将S / (M / 53/47)) = 2820 拿出来拆分)


  若N包含k个质因子a, t为满足a^t > 47(显然t >= 2)的最小整数,则 k < 2*t-1


(否则若将t个a拆分成47,由 (k+1)*1 – (k-t+1) * 2 = 2*t-k-1 <=0,


可知拆分后得到的数更优,与N最优矛盾)。


因此a3 <=2*4-2=6,


a5 <= 2*3 – 2 = 4, 


a7 <= 2*2-2 = 2


a11 <= 2*2-2 = 2


 


若a7 <=1, 则a3<=4,否则可以将2个3拆成1个7,得到更优解。由


S/(3^4*5^4)/ (7*11*13*17*19*23*29*31*37*41)  = 35


(能得到的最多因子个数为25*2^10 < 3*2^14不是最优解)


因而 a7 = 2


 


( 若az = 2, ax = a, ay =b 且 z > x * y,若不能将 z拆分成 x * y,则有


   (a+1)*(b+1)*3 > (a+2)*(b+2)*2,即 (a-1)*(b-1) >= 7 )


 


若a23=2则可将1个23拆成3和7,由 (1+a3)*3*3 – (1+a3+1)*4*2 = a3-7<0


可知得到的数更优,与假设矛盾,因而 a23<=1,


由于 S/(3^6*5^4)/(7*11*13*17*19)^2 = 387 > 23因而 一定含有因子23,a23 = 1


 


若a31=0,则 a5 = 2(否则,5*7合并成31,得到更优解)


由 2^64 / (3^6*(5*7*11*13*17*19)^2 * 23 * 29) = 14


可知,该情况下得到的最大数不是最优, 因而 a31 = 1


 


(若a17 =2则 a3>=5, a5=3 或 a3>=4 a5=4,否则可以将17拆分成3*5)


 


利用前面的结论,


  a3 >= a5 >= a7 …


  a3 <= 6  a5 <= 4  a7 = 2  a23 = 1  a31 = 1  a47 = 0


可在较短时间内搜索出满足上述条件的因子个数最多的奇数,再与局部最优解R1进行比较,就可以确定最优解。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值