求输出和为n的所有连续自然数序列
这是编程之美中的一道题。编程之美中的题目是这样的:
1+2=3
4+5=9
2+3+4=9
等式的左边都是两个或者两个以上的连续自然数相加,那么是不是所有的整数都可以写成这样的形式?
问题1:写个程序,对于一个64位正整数,输出它所有可能的连续自然数之和(两个数以上)的算式。
问题2:哪些数字不能不能表示成连续自然数之和?能否证明。
问题3:在64位正整数的范围内,子序列数目最多的数是哪一个?能否用数学知识推导出来。
-------------------
问题1:
这个最先想到方法就是蛮力法。对于一个i (1<i<n)进行测试,看一i开头的自然数序列是不是能得到n这个和。C#代码如下:
public static void getSequence(int S)
{
writer.WriteLine("--------"+S+"---------");
int sum ;
for (int i = ; i < S; i++)
{
sum = ;
List<int> ns=new List<int>();
for (int j = i; j <= S&&sum<S; j++)
{
sum += j;
ns.Add(j);
if (sum == S)
{
printArray(ns);
break;
}
}
}
}
这个算法的时间负责度是O(n*n)级别的。
一些改进可以来对数学公式的应用。
假设这个连续序列为m,m+1,m+2,…,m+k-1,其中m>0,k>1.那么s=(m+m+k-1)*k/2,即2*s=(2*m+k-1)*k.只要找到m和k的值,这个序列就可以求出. m和k有何关系? 容易发现,(2*m+k-1)和k肯定是前者大于后者,并且一个为奇数一个为偶数。因此将2*s进行分解表示为2*s=2^t*a.其中a是个奇数,将a进行因式分解变成a=b*c,那么2*s=2^t*b*c.求出所有2*s的一个奇数和一个偶数的因子分解,就找到了对应的2*m+k-1和k,进而能够解出m和k.
下面是上述思想的java实现。
public void getSequence(int S){
System.out.println("------"+S+"------");
int t=get2(2*S);
int a=(int)(2*S/Math.pow(2, t));
if(a==1){
System.out.println(String.format("%d has no solution", S));
return;
}
ArrayList<Integer[]> pairs=getFactors(a);
for(Integer[] pa:pairs){
for(int i=0;i<2;i++){
int b=pa[i];
int j=(i+1)%2;
int c=pa[j];
int k=0;
int m=0;
k=(int)Math.min(Math.pow(2, t)*b,c);
if(k>1){
m=(int)(Math.max(Math.pow(2, t)*b,c)-k+1)/2;
printSequence(S,m,k);
}
if(b==c){
break;
}
}
}
}
public ArrayList<Integer[]> getFactors(int a){
ArrayList<Integer[]> factorPair=new ArrayList<Integer[]>();
for(int i=1;i<=(int)Math.floor(Math.sqrt(a));i++){
if(a%i==0){
Integer[] pair=new Integer[2];
pair[0]=i;
pair[1]=a/i;
factorPair.add(pair);
}
}
return factorPair;
}
public int get2(int a){
int t=0;
while(a%2==0){
t++;
a=a/2;
}
return t;
}
public void printSequence(int S,int m,int k){
StringBuilder sb=new StringBuilder();
sb.append(S);
sb.append("=");
for(int i=0;i<k;i++){
sb.append(m+i);
sb.append("+");
}
String str=sb.toString();
System.out.println(str.substring(0,str.length()-1));
}
从上面的解的过程,我们也发现了问题2的答案。那就是当n为2的幂次方时,n不能够被分解为这样的连续自然数的和的形式。因为这时n=(m+m+k-1)*k/2是无解的。
关于问题3,看来分解序列最多的生成的a能够分解成不同b*c数最多的那个,注意a是个奇数。64位正整数的范围内,哪个奇数能够产生最多的这样的因式分解?从网上看到这个数应该是3^n这样的形式,因为3是所有质数的最小值,最细刻度的划分,可能会产生最多中划分形式。这样说也有理由,但是不能严谨的证明。而且不用64位,用4位,即n为0到15的正整数,子序列最多的不是9而是15。这样看来3^n不一定正确,但是我觉得这个思路是对的--尽可能的细划分。有时间在研究吧
求输出和为n的所有连续自然数序列的更多相关文章
- 输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)
package leetcode;import edu.princeton.cs.algs4.Cycle;import java.util.ArrayList;import java.util.Arr ...
- 输入一个正整数n,输出所有和为n的连续正整数序列
public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (true) { System. ...
- 剑指offer四十一之和为S的连续正数序列
一.题目 题目描述:小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数 ...
- (剑指Offer)面试题41:和为s的连续正数序列
题目: 输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数).例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1-5,,4-6和7-8. 思路: ...
- 剑指Offer——和为S的连续正数序列
题目描述: 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久, ...
- 剑指Offer - 九度1354 - 和为S的连续正数序列
剑指Offer - 九度1354 - 和为S的连续正数序列2013-11-23 02:02 题目描述: 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100. ...
- Go语言实现:【剑指offer】和为S的连续正数序列
该题目来源于牛客网<剑指offer>专题. 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数 ...
- 【剑指Offer面试编程题】题目1354:和为S的连续正数序列--九度OJ
题目描述: 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久, ...
- 【剑指Offer】和为S的连续正数序列 解题报告(Python)
[剑指Offer]和为S的连续正数序列 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interview ...
随机推荐
- Arcgis andoid开发之应用百度地图接口实现精准定位与显示
怀着激动.兴奋的心情,在这个漫天柳絮的季节写下了这片博文,为什么呢,因为困扰我很久的一个技术性的问题得到了解决,发次博文,供大家参观.学习,同时,也以慰藉我长期困扰的心情,好了,废话不再,言归正传,看 ...
- 你真的对java static了解吗,代码优化可能更加简单
static修饰的成员变量和成员方法独立于该类的任何对象.也就是说,它不依赖类特定的实例,被类的所有实例共享. 只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们.因此,s ...
- Android使用Http协议访问网络——HttpConnection
套路篇 使用HttpConnection访问网络一般有如下的套路: 1.获取到HttpConnection的实例,new出一个URL对象,并传入目标的网址,然后调用一下openConnection() ...
- php之opcodes
opcode是一种php脚本编译之后的语言. 例如: <?php echo "Hello World"; $a = 1 + 1; echo $a; ?> php执行这段 ...
- Ubuntu16.04配置apache+php+mysql
命令行配置apache input sudo apt-get install apache2 done! 命令行配置mysql 参见: MySQL install and setting 命令行配置p ...
- Ant入门之引用外部jar文件
笔者在java项目开发中经常遇到引用外部Jar包的情况,使用ant打包过程中需要对其引用.现在此简单记忆以飨来者. 此处引用Log4j,具体程序HelloLog4j.java: package oat ...
- 【学习】Git和Github菜鸟入门
Git 是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本管理. 目录(自己创建吧) 生成ssh密钥:ssh-keygen -t rsa -C "邮箱" ...
- 【英语】Bingo口语笔记(83) - hell系列
- 【转】 史上最详尽的平衡树(splay)讲解与模板(非指针版spaly)
ORZ原创Clove学姐: 变量声明:f[i]表示i的父结点,ch[i][0]表示i的左儿子,ch[i][1]表示i的右儿子,key[i]表示i的关键字(即结点i代表的那个数字),cnt[i]表示i结 ...
- Eclipse环境搭建配置操作
1.选择window 2.设置字体 3.设置编码格式:国际编码:UTF-8 第一个地方设置编码格式 第二个地方设置编码格式:这个更重要些 4.配置26个英文小写字母. 作用:能够在开发时提示你,快速开 ...