Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 解方程的算法_Java_Algorithm_Math_Brute Force_Equation Solving - Fatal编程技术网

Java 解方程的算法

Java 解方程的算法,java,algorithm,math,brute-force,equation-solving,Java,Algorithm,Math,Brute Force,Equation Solving,我在“算法和数据结构”课程中遇到了这个问题 你有一个方程x^2+s(x)+200·x=N,其中x和N是自然数,s(x)是数字x的位数之和 在输入上,我们有N和A,B,这样A≤B和A,B≤1,000,000,000. 你需要检查在区间[a,B]中是否有一个自然数x来解方程。如果找到,您需要返回该数字,否则返回-1 我通过使用一些数学和一点修改过的蛮力算法解决了这个问题。但是有没有更有效的(基于算法的)方法来解决这个问题 这是我的代码: import java.io.BufferedReader;

我在“算法和数据结构”课程中遇到了这个问题

你有一个方程x^2+s(x)+200·x=N,其中x和N是自然数,s(x)是数字x的位数之和

在输入上,我们有N和A,B,这样A≤B和A,B≤1,000,000,000. 你需要检查在区间[a,B]中是否有一个自然数x来解方程。如果找到,您需要返回该数字,否则返回-1

我通过使用一些数学和一点修改过的蛮力算法解决了这个问题。但是有没有更有效的(基于算法的)方法来解决这个问题

这是我的代码:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Range {
    
    static int proveri(long N, long A, long B) {
        long res = 0;
        long start = (long)((-200 + Math.sqrt(4*N + 4))/2);
        //System.out.println(start);
        for (long i = Math.max(A, start); i <= B; i++) {
            res = i * i + S(i) + 200 * i;
            if(res == N)
                return (int)i;
            if(res > N)
                return -1;
        }
        
        return -1;
    }
    
    static int S(long x) {
        int sum = 0;
        while(x > 0) {
            sum += x % 10;
            x /= 10;
        }
        return sum;
    }
    
    public static void main(String[] args) throws Exception {
        int i,j,k;
        
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        long N = Long.parseLong(br.readLine());
        
        StringTokenizer st = new StringTokenizer(br.readLine());
        long A = Long.parseLong(st.nextToken());
        long B = Long.parseLong(st.nextToken());
        
        int res = proveri(N, A, B);
        System.out.println(res);
        
        br.close();
        
    }
    
}
导入java.io.BufferedReader;
导入java.io.InputStreamReader;
导入java.util.StringTokenizer;
公共类范围{
静态整数验证(长N、长A、长B){
长res=0;
长启动=(长)(-200+数学sqrt(4*N+4))/2);
//系统输出打印项次(开始);
for(long i=Math.max(A,start);i N)
返回-1;
}
返回-1;
}
静态整数S(长x){
整数和=0;
而(x>0){
总和+=x%10;
x/=10;
}
回报金额;
}
公共静态void main(字符串[]args)引发异常{
int i,j,k;
BufferedReader br=新的BufferedReader(新的InputStreamReader(System.in));
long N=long.parseLong(br.readLine());
StringTokenizer st=新的StringTokenizer(br.readLine());
long A=long.parseLong(st.nextToken());
long B=long.parseLong(st.nextToken());
int res=proveri(N,A,B);
系统输出打印项次(res);
br.close();
}
}

这里有一种方法,可以减少搜索数量

考虑方程anxn+ an-1xn-1+…+a1x+a0=0。 有理根定理指出,如果x=p/q是一个解, 然后p除以a0,q除以an

在你的例子中,an是1,a0等于S(x)-N。因此,我们知道任何解都必须除以S(x)-N

这就是ben75的秘诀所在。由于S(x)不能大于81,我们可以循环遍历S(x)的所有可能值,并分别求解。大概是这样的:

S(x)的每个可能值的

循环通过S(x)-N的每个因子x
检查它是否在A和B之间,是否其数字总和为S(x)
如果它是x*x+200x+S(x)=N的解。
如果是,请退回。
返回-1
还有一种非常巧妙的方法可以让你循环一个数的所有因子,但我会让你自己计算出来,因为这是一门课程。我的提示是看一个数的素数分解。

对于方程x^2+s(x)+200·x=N,考虑

x^2 + 200·x + (N - s(x)) = 0
对于具有整数解的a*x^2+b*x+c=0方程的解,我们需要:

b^2 - 4*a*c >= 0 and must be a perfect square
因此200^2-4*(N-s(x))>=0和一个平方或

10000>=(N-s(x))和(10000-(N-s(x))必须是平方。因此,平方值小于10000,因此最多可以有100个值需要检查。如果N的值正确,则可以小得多


还要注意的是,由于N<10000,s(x)最多可以是36。这些应该会将范围缩小很多。

看看你可能使用的10^18数量级的数字的范围。如果我能给你任何实质性的改进,我们将发布更具算法性的方法。你可以跟踪s(x)随着时间的推移,从0开始。我没有时间发布代码,但这可以简化事情。只要观察从0开始递增的数字总和是如何变化的,你就会看到一个模式。@AndyG是的,我知道它们是连接的,但有时我仍然需要进行~100000000次检查。s(x)取决于x,你仍然可以称之为二次方程吗?它仍然可以被称为二次方程,因为二次方程的解决机制只是一个平方的完成。没有需要满足的自变量标准。谢谢你的解决方案。我认为这里缺少一些明显的算法,但看起来很简单这个问题一定涉及到一些数学问题。我的解决方案已经使用了类似的东西,所以我将保持这样。也要感谢@user1952500。
b^2 - 4*a*c >= 0 and must be a perfect square