我正在编写用于计算整数可以表示为连续整数之和的方式的代码。例如
15 =(7 + 8),(1 + 2 + 3 + 4 + 5),(4 + 5 + 6)。因此,15的方式等于3。 现在输入大小可以是<= 10 ^ 12。我的程序工作正常,直到10 ^ 7(我想是的,但不确定,因为我没有在任何在线评判中检查它。随意检查代码)
但是只要我给它10 ^ 8或更高的整数作为输入。它抛出许多运行时异常(它不显示运行时错误)。提前谢谢。
import java.io.*;
//sum needs to contain atleast 2 elements
public class IntegerRepresentedAsSumOfConsecutivePositiveIntegers
{
public static long count = 0;
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
long num = Long.parseLong(br.readLine()); //Enter a number( <=10^12)
driver(num);
System.out.println("count = " + count);
}
public static void driver(long num)
{
long limit = num / 2;
for(long i = 1 ; i <= limit ; i++)
{
func(i,num);
}
}
public static void func(long i,long num)
{
if(i < num)
{
func(i + 1,num - i);
}
else if(i > num)
{
return;
}
else
{
count++;
}
}
}
答案 0 :(得分:1)
使用一些数学:如果差异1的算术级数从a0
开始并且包含n
个项目,则其总和为
S = (2 * a0 + (n-1))/2 * n = a0 * n + n * (n-1) / 2
请注意,第二个加数作为二次函数上升。因此,我们不会检查范围a0
中的所有S/2
,而是检查所有n
是否更小范围
nmax = Ceil((-1 + Sqrt(1 + 8 * S)) / 2)
(我使用了一些更高的近似值)。
只测试下一个表达式是否给出整数正结果
a0 = (S - n * (n - 1) / 2) / n
答案 1 :(得分:0)
当你的输入大小与你的情况一样大时,递归函数并不合适。
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);
<强>输出强>:
Enter a number <=10^12: 15
3
Enter a number <=10^12: 1000000000
9
BUILD SUCCESSFUL (total time: 10 seconds)
答案 2 :(得分:0)
正如@MBo所指出的,如果一个S
号码可以划分为n
个连续的部分,则S - T(n)
必须可以被n
整除,其中T(n)
是第n triangular number个,因此您可以在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;
}
更多的数学会产生更简单的方法。 Wikipedia说:
正数的礼貌被定义为可以表示为连续整数之和的方式的数量。对于每个x,x的礼貌等于x的奇数除数大于1。
另见:OEIS A069283
因此,一个有很多优化空间的简单解决方案是:
// 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;
}
答案 3 :(得分:0)
有一个非常好的证据可以通过求解唯一的奇数因子(Reference)来确定答案。基本上,对于目标值的每个奇数因子,存在该因子的奇数系列数乘以其平均值以产生目标值,或者存在等于该因子的奇数平均值,其可以乘以偶数大小的两倍系列达到目标值。
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;
}