Java 将整数表示为连续正整数之和
我正在编写代码,用于计算一个整数可以表示为连续整数之和的方式的数量。比如说 15=(7+8),(1+2+3+4+5),(4+5+6)。所以15条路的数量等于3条。Java 将整数表示为连续正整数之和,java,math,Java,Math,我正在编写代码,用于计算一个整数可以表示为连续整数之和的方式的数量。比如说 15=(7+8),(1+2+3+4+5),(4+5+6)。所以15条路的数量等于3条。 现在输入大小可以递归函数不适用于像您的案例这样的大输入大小 java调用堆栈的最大深度约为8900个调用,有时仅在7700个调用堆栈溢出后发生,因此它实际上取决于程序输入大小 试试这个算法,我认为它对你的问题有效: 它可以正常工作,直到10^9,然后需要更多的时间来完成程序的运行 long sum = 0; int c
现在输入大小可以递归函数不适用于像您的案例这样的大输入大小 java调用堆栈的最大深度约为8900个调用,有时仅在7700个调用堆栈溢出后发生,因此它实际上取决于程序输入大小 试试这个算法,我认为它对你的问题有效: 它可以正常工作,直到
10^9
,然后需要更多的时间来完成程序的运行
long sum = 0;
int count = 0;
long size;
Scanner in = new Scanner(System.in);
System.out.print("Enter a number <=10^12: ");
long n = in.nextLong();
if(n % 2 != 0){
size = n / 2 + 1;
}
else{
size = n / 2;
}
for(int i = 1; i <= size; i++){
for(int j = i; j <= size; j++){
sum = sum + j;
if(sum == n){
sum = 0;
count++;
break;
}
else if(sum > n){
sum = 0;
break;
}
}
}
System.out.println(count);
长和=0;
整数计数=0;
长尺寸;
扫描仪输入=新扫描仪(系统输入);
System.out.print(“输入一个数字使用一些数学:如果差为1的算术级数以a0
开始,并包含n
项,则其总和为
S = (2 * a0 + (n-1))/2 * n = a0 * n + n * (n-1) / 2
请注意,第二个和作为二次函数上升。因此,我们不必检查范围S/2
中的所有a0
,而可以检查范围较小的所有n
nmax = Ceil((-1 + Sqrt(1 + 8 * S)) / 2)
(我使用了更高的近似值)
只需测试下一个表达式是否给出整数正结果
a0 = (S - n * (n - 1) / 2) / n
正如@MBo所指出的,如果一个数字S
可以被划分成n
连续的部分,那么S-T(n)
必须可以被n
整除,其中T(n)
是第n个,因此你可以在O(sqrt(S))
时间内计算分区的数量
// number of integer partitions into (at least 2) consecutive parts
static int numberOfTrapezoidalPartitions(final long sum) {
assert sum > 0: sum;
int n = 2;
int numberOfPartitions = 0;
long triangularNumber = n * (n + 1) / 2;
while (sum - triangularNumber >= 0) {
long difference = sum - triangularNumber;
if (difference == 0 || difference % n == 0)
numberOfPartitions++;
n++;
triangularNumber += n;
}
return numberOfPartitions;
}
再多学一点数学,就会得到一种更简单的方法。比如:
正数的礼貌性定义为它可以表示为连续整数之和的方式的数量。对于每个x,x的礼貌性等于x的大于1的奇数因子的数量
另见:OEIS
因此,一个有很大优化空间的简单解决方案是:
// number of odd divisors greater than one
static int politeness(long x) {
assert x > 0: x;
int p = 0;
for (int d = 3; d <= x; d += 2)
if (x % d == 0)
p++;
return p;
}
//大于1的奇数除数的数目
静态int礼貌(长x){
断言x>0:x;
int p=0;
对于(int d=3;d有一个非常好的证明,答案可以通过求解唯一的奇数因子()。基本上,对于目标值的每个奇数因子,存在该因子的奇数序列乘以其平均值以产生目标值,或存在等于该因子的奇数平均值,该因子可乘以双倍偶数序列以达到目标值
public static int countUniqueOddFactors(long n) {
if (n==1) return 1;
Map<Long, Integer> countFactors=new HashMap<>();
while ((n&1)==0) n>>>=1; // Eliminate even factors
long divisor=3;
long max=(long) Math.sqrt(n);
while (divisor <= max) {
if (n % divisor==0) {
if (countFactors.containsKey(divisor)) {
countFactors.put(divisor, countFactors.get(divisor)+1);
} else {
countFactors.put(divisor, 1);
}
n /= divisor;
} else {
divisor+=2;
}
}
int factors=1;
for (Integer factorCt : countFactors.values()) {
factors*=(factorCt+1);
}
return factors;
}
公共静态int countUniqueOddFactors(长n){
如果(n==1)返回1;
Map countFactors=new HashMap();
而((n&1)==0)n>>>=1;//消除偶数因子
长除数=3;
long max=(long)Math.sqrt(n);
虽然(除数为什么不计算-3+-2+-1+0+1+2+3+4+5+6
?可能是整数溢出,也可能是由于递归调用过多而导致的溢出。如果您从未听说过动态编程,现在是学习的好时机。有一个数学公式可以计算第一个n
正整数的和,如下所示:n*(n+1)/2
@DawoodibnKareem Title表示连续的正整数。@Bubletan Ooh抱歉。我阅读了问题的文本而不是标题。我也为输入“10^9”运行了您的算法,并且我没有使用任何计时器,但这两种方法所用的时间几乎相同。@colt您将在其上进行测试。您应该尝试实现一个解决方案如果您希望提高效率,请根据@plasmacel的评论。@Colt。很抱歉,我已更新了代码。我正在对其进行审阅。运行时错误已得到解决,但所花费的时间几乎与您的相同。@Colt。顺便说一句,您对java调用堆栈大小的看法是正确的。:)
// number of odd divisors greater than one
static int politeness(long x) {
assert x > 0: x;
int p = 0;
for (int d = 3; d <= x; d += 2)
if (x % d == 0)
p++;
return p;
}
public static int countUniqueOddFactors(long n) {
if (n==1) return 1;
Map<Long, Integer> countFactors=new HashMap<>();
while ((n&1)==0) n>>>=1; // Eliminate even factors
long divisor=3;
long max=(long) Math.sqrt(n);
while (divisor <= max) {
if (n % divisor==0) {
if (countFactors.containsKey(divisor)) {
countFactors.put(divisor, countFactors.get(divisor)+1);
} else {
countFactors.put(divisor, 1);
}
n /= divisor;
} else {
divisor+=2;
}
}
int factors=1;
for (Integer factorCt : countFactors.values()) {
factors*=(factorCt+1);
}
return factors;
}