在 Java 代码中获取 NZEC [英] Getting NZEC in Java Code

查看:36
本文介绍了在 Java 代码中获取 NZEC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解决问题 http://www.codechef.com/APRIL12/问题/饺子/

我在 codechef 上遇到运行时错误 NZEC.我在互联网上搜索但没有设法使我的代码成功.

I'm getting runtime error NZEC on codechef. I searched on the Internet but did not manage to make my code succeed.

这是我的代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;

public class Main {

    public BigInteger gcd(BigInteger a,BigInteger b){
        if(b.compareTo(BigInteger.valueOf(0)) == 0)
            return a;
        return gcd(b,a.mod(b));
    }

    public static void main(String[] args) {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str;
        int t = 1;
        Main obj = new Main();
        try{
            str = br.readLine();
            t = Integer.parseInt(str);
        }
        catch(IOException e){
            System.out.println("error");
        }

        for(int w = 0; w < t; w++){
            BigInteger a = BigInteger.valueOf(1);
            BigInteger b = BigInteger.valueOf(1);
            BigInteger c = BigInteger.valueOf(1);
            BigInteger d = BigInteger.valueOf(1);
            BigInteger k = BigInteger.valueOf(1);
            try{
                str = br.readLine();
                String s[] = str.split(" ");
                a = new BigInteger(s[0]);
                b = new BigInteger(s[1]);
                c = new BigInteger(s[2]);
                d = new BigInteger(s[3]);
                k = new BigInteger(s[4]);
            }
            catch(IOException e){
                System.out.println("error");
            }

            BigInteger g1,g2,num;
            if(a.compareTo(b) < 0){
                num = a;
                a = b;
                b = num;
            }

            if(c.compareTo(d) < 0){
                num = c;
                c = d;
                d = num;
            }

            g1 = obj.gcd(a,b);
            g2 = obj.gcd(c,d);

            if(g1.compareTo(g2) < 0){
                num = g1;
                g1 = g2;
                g2 = num;
            }
            BigInteger g3 = obj.gcd(g1,g2);

            BigInteger l = g1.divide(g3);
            l = l.multiply(g2);

            BigInteger res = k.divide(l);
            BigInteger fin = res.multiply(BigInteger.valueOf(2));
            fin = fin.add(BigInteger.valueOf(1));
            System.out.println(fin);
        }
    }

}

谁能告诉我我哪里做错了?

can anyone please tell me where am I doing wrong?

推荐答案

除非出现不太可能的情况,我看到的该程序获得非零退出代码的唯一可能性是

Barring unlikely scenarios, the only possibilities for getting a nonzero exit code with that programme that I see are

  • 除以零,但如果输入符合规范,则不会发生这种情况
  • 意外的输入格式导致 NumberFormatException

所以我正在研究后一个假设.一种简单的检查方法是将两个 catch(IOException e) 替换为 catch(Exception e),如果输入确实不是您期望的格式,您然后会得到错误的答案"(但更改后得到 WA 并不能证明假设是正确的).

So I'm working off the latter hypothesis. An easy way to check would be to replace the two catch(IOException e) with catch(Exception e), if the input is indeed not in the format you expect, you would get a 'Wrong Answer' then (but getting a WA after the change doesn't prove the hypothesis correct).

第一行的任何额外空格都会导致 Integer.parseInt(str) 中的 NumberFormatException.任何后面的行上的额外空格将导致 str.split(" ") 创建的 String[] 有五个以上的元素,如果在第五个数字之前出现任何这样的情况在该行中,程序将尝试创建 BigInteger.valueOf(""),这再次导致 NumberFormatException.所以我会推荐一个更健壮的输入法,例如一个 java.util.Scanner 可以毫无问题地处理额外的空白.此处使用的方法是 nextInt() 用于测试用例的数量,nextLong() 用于其余.

Any additional whitespace on the first line would cause a NumberFormatException in Integer.parseInt(str). Additional whitespace on any later line would cause the String[] created by str.split(" ") to have more than five elements, if any such occurs before the fifth number on that line, the programme would try to create BigInteger.valueOf(""), which again causes a NumberFormatException. So I would recommend a more robust input method, for example a java.util.Scanner that can deal with additional whitespace without problems. The methods to use here are nextInt() for the number of test cases and nextLong() for the rest.

Scanner scn = new Scanner(System.in);
int t = scn.nextInt();
for(int w = 0; w < t; w++){
    BigInteger a = BigInteger.valueOf(scn.nextLong());
    BigInteger b = BigInteger.valueOf(scn.nextLong());
    BigInteger c = BigInteger.valueOf(scn.nextLong());
    BigInteger d = BigInteger.valueOf(scn.nextLong());
    BigInteger k = BigInteger.valueOf(scn.nextLong());

    BigInteger g1,g2,num;
    ...

如果该更改导致接受,则 NZEC 的原因可能是意外的输入格式.

If that change leads to an accept, the cause for the NZEC was likely an unexpected input format.

你问

谁能告诉我我哪里做错了?

can anyone please tell me where am I doing wrong ?

所以我会指出一些并非严格不正确但错误的做法/毫无意义的事情.

so I'll point out some more things that are not strictly incorrect, but bad practice/pointless.

public BigInteger gcd(BigInteger a,BigInteger b){
    if(b.compareTo(BigInteger.valueOf(0)) == 0)
        return a;
    return gcd(b,a.mod(b));
}

那个方法应该是static.它不涉及任何状态,因此必须创建一个对象来调用它是很糟糕的.

That method should be static. It involves no state whatsoever, so having to create an object just to call it is bad.

另一点,与问题中可能出现的小数无关,但与处理大数有关,是您使它递归.Java 通常(如果有的话)不执行尾调用优化,并且调用堆栈通常只能处理几千个调用,因此使用递归实现可能会导致 StackOverflowError.(但由于欧几里德算法的调用深度是对数的,所以这只涉及更大的数字.)

Another point, not pertinent for small numbers like those that may appear in the problem, but relevant if you deal with large numbers, is that you made it recursive. Java usually (if ever) doesn't perform tail call optimisation, and the call stack can usually only handle a few thousand calls, so you risk a StackOverflowError with the recursive implementation. (But since the call depth is logarithmic for the Euclidean algorithm, that only concerns larger numbers.)

catch(IOException e){
    System.out.println("error");
}

捕获异常只是为了将错误"打印到标准输出是不好的.如果你不能做一些更有意义的事情来处理它,就不要抓住它.

Catching an exception just to print "error" to stdout is bad. If you can't do something more meaningful to handle it, don't catch it at all.

for(int w = 0; w < t; w++){
    BigInteger a = BigInteger.valueOf(1);
    BigInteger b = BigInteger.valueOf(1);
    BigInteger c = BigInteger.valueOf(1);
    BigInteger d = BigInteger.valueOf(1);
    BigInteger k = BigInteger.valueOf(1);

为变量分配一个虚拟值是没有意义的,它们将立即被设置为它们的真实值(否则程序会在失败时死亡).

Assigning a dummy value to the variables is pointless, they will be immediately set to their real values (or the programme should die if that fails).

    try{
        str = br.readLine();
        String s[] = str.split(" ");
        a = new BigInteger(s[0]);
        b = new BigInteger(s[1]);
        c = new BigInteger(s[2]);
        d = new BigInteger(s[3]);
        k = new BigInteger(s[4]);
    }
    catch(IOException e){
        System.out.println("error");
    }

无意义的catch又一次.

    if(a.compareTo(b) < 0){
        num = a;
        a = b;
        b = num;
    }

    if(c.compareTo(d) < 0){
        num = c;
        c = d;
        d = num;
    }

我怀疑您交换是为了避免被除数小于除数的 mod 操作.在某些地方,这种微优化很重要,但这不是其中之一.如果你有理由关心这样的小事,那么还有很多事情要做.例如,手头的问题可以使用 long 解决(有一个地方需要调整算法以避免可能的溢出),并且该原始类型的更快的算术将使小型算法相形见绌您可能会从这里的交换中获得收益.

I suspect you swap to avoid a mod operation where the dividend is smaller than the divisor. There are places where such micro-optimisations are important, but this is not one of them. If you had reason to care about small things like that, there'd be much more to do. For example, the problem at hand can be solved using long (there's one place where the algorithm would need to be adapted to avoid possible overflow), and the much faster arithmetic of that primitive type would dwarf the small gain you might get from the swap here.

这篇关于在 Java 代码中获取 NZEC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆