zoukankan      html  css  js  c++  java
  • 一个自然数拆分成连续自然数的和

    1. 能否拆分

        结论:除了 $2^n$ 之外,其他自然数均可以拆分

        所有奇数都能写成 $2i + 1$ 的形式,因此至少可以拆成 $(i, i+1)$,所以奇数可以拆分

        偶数里边,奇数倍数的可以拆分,其他的(也就是 $2^n$) 无法拆分

     1 boolean ifConsistOfConsecutiveInteger(int n) {
     2     if (n <= 0) {
     3         return false;
     4     }
     5     boolean result = false;
     6     if ((n & (n - 1)) != 0) {
     7         result = true;
     8     }
     9 
    10     return result;
    11 }

    2. 输出可以拆分成的各种形式

        2.1 数学方法

              以 $a$ 表示连续自然数中的第一个,则

              $n = a + (a + 1) + (a + 2) + ... + (a + k - 1)$

              整理一下

              $2n = 2ka + k^2 - k$

              整理成关于 $k$ 的一元二次方程

         $k^2 + (2a - 1)k - 2n = 0$

         解这个方程,$Delta = (2a -1)^2 + 8n$

       $k = (1 - 2a + sqrt{Delta})/2$

          然后,考虑三个问题

          1) 连续自然数序列里的第一个数必然小于等于 $n/2$,如果大于的话,再和后面的数相加肯定大于 $n$

          2) $Delta$ 开方之后必须是整数

          3) $1 - 2a + sqrt{Delta}$ 必须是偶数,否则除以 $2$ 会出现小数

        代码如下($n$ 太大时不适用,会有溢出):

     1 void printExpression(int n) {
     2     long first;
     3     long incr;
     4     for (int i = 1; i <= n / 2; i++) {
     5         first = i;
     6         long delta = (2 * first - 1) * (2 * first - 1) + 8 * n;
     7         long sqrt_delta = (int) Math.sqrt(delta);
     8 
     9         if (sqrt_delta * sqrt_delta == delta && sqrt_delta % 2 != 0) {
    10             incr = (sqrt_delta - (2 * first - 1)) / 2;
    11             System.out.println("num of consecutive integer is " + incr);
    12             for (int j = 1; j <= incr; j++) {
    13                 System.out.print(first + j - 1 + " ");
    14             }
    15             System.out.println();
    16         }
    17     }
    18 }

         2.2 双指针解法(参考剑指 Offer)

     1 void printExpression2(int n) {
     2     int small = 1;
     3     int big = 2;
     4     int sum = small + big;
     5     while (small <= n / 2) {
     6         if (sum == n) {
     7             for (int i = small; i <= big; i++) {
     8                 System.out.print(i + " ");
     9             }
    10             System.out.println();
    11         }
    12         while (sum > n) {
    13             sum -= small;
    14             small++;
    15 
    16             if (sum == n) {
    17                 for (int i = small; i <= big; i++) {
    18                     System.out.print(i + " ");
    19                 }
    20                 System.out.println();
    21             }
    22         }
    23 
    24         big++;
    25         sum += big;
    26     }
    27 }
  • 相关阅读:
    如何复制word的图文到UMEditor中自动上传
    如何复制word的图文到百度编辑器中自动上传
    如何复制word的图文到百度ueditor中自动上传
    java实现大文件上传源码
    java实现大文件上传控件
    java实现大文件上传组件
    java实现大文件上传插件
    html 常用标签及基本用法
    Web最佳实践阅读总结(1)
    基于DevOps理论与人工智能技术的银行业务可用性管控
  • 原文地址:https://www.cnblogs.com/ainsliaea/p/11221186.html
Copyright © 2011-2022 走看看