-3

私は InterviewStreet で練習プログラムに取り組んでおり、5.15xx 秒の時間で実行されるソリューションを持っていますが、Java ソリューションに許可されている最大時間は 5 秒です。5 秒未満にするために、ここにあるものでできることはありますか? 256 MB の制限もあるので、私が言える限り、これは問題に対する最も時間とメモリ効率の良い解決策です...

編集: N と K の可能な値は、N <= 10^9 および K <= N です。これが、BigInteger を使用してすべてを行うことを選択した理由です。試行の最大数は 10000 です。したがって、基本的には、試行の数を入力し、次に試行の数ごとに整数値のペアを入力すると、プログラムは 2 番目のループで方程式の 2 項係数の 3 つのバージョンを計算します。すべてを配列に読み込んでから配列を処理し、結果を 3 番目の配列に入れて 3 番目のループで処理する方が速いと考えました。すべてを同じループで実行しようとしましたが、実行速度が遅くなりました。

二項係数を計算するために 3 つまたは 4 つの異なるアルゴリズムを試しました (nCr - または n は r を選択します。すべて同じことを言う別の方法です)。一部のアルゴリズムには、c[n][k] のような 2 次元配列が含まれます。これは、私が提出した唯一の解決策であり、何らかのメモリ エラーが発生しませんでした。nCr * nCr の答えはかなり大きくなるので、答えは output mod (10 ^ 6) + 3 である必要があります。プログラムの実行例は次のとおりです。

3

4 1
5 2
90 13

2
5
815483

カウントするためにマシンに渡す必要があるため、より高速なマシンでは実行できません。基本的に私はコードを送信し、テストケースに対して実行します。入力が上記の範囲内。

そしてプログラム自体:

import java.math.BigInteger;
import java.util.Scanner;

public class Solution {

public BigInteger nCr(int n, int r) {
    if (r > n ) {
        return BigInteger.ZERO;
    }

    if (r > n / 2) {
        r = n - r;
    }
    BigInteger result = BigInteger.ONE;

    for (int i = 0; i < r; i++) {
        result = result.multiply(BigInteger.valueOf(n - i));
        result = result.divide(BigInteger.valueOf(i + 1));
    }
    return result;
}

public static void main(String[] args) {
    Scanner input = new Scanner( System.in );
    BigInteger m = BigInteger.valueOf(1000003);
    Solution p = new Solution();
    short T = input.nextShort(); // Number of trials
    BigInteger intermediate = BigInteger.ONE;
    int[] r = new int[T];
    int[] N = new int[T];
    int[] K = new int[T];

    short x = 0;

    while (x < T) {
    N[x] = input.nextInt();
    K[x] = input.nextInt();
    x++;
    }

    x = 0;
    while (x < T) {
    if (N[x] >= 3) { 
            r[x] = ((p.nCr(N[x] - 3, K[x]).multiply(p.nCr(N[x] + K[x], N[x] - 1))).divide(BigInteger.valueOf((N[x] + K[x]))).mod(m)).intValue();
        } else {
            r[x] = 0;
    }
    x++;
    }

    x = 0;
    while (x < T) {
    System.out.println(r[x]);
    x++;
    }
}

}

4

2 に答える 2

0

アルゴリズムが何を達成しようとしているのか完全にはわかりませんが、投稿のタグ付けに基づいて、二項係数で何かを推測しています.

私の提案が結果を変更するかどうかを確認する必要がありますが、2 つの while ループをマージできるようです。

オリジナル:

while (x < T) {
    N[x] = input.nextInt();
    K[x] = input.nextInt();
    x++;
}

x = 0;
while (x < T) {
if (N[x] >= 3) { 
        r[x] = ((p.nCr(N[x] - 3, K[x]).multiply(p.nCr(N[x] + K[x], N[x] - 1))).divide(BigInteger.valueOf((N[x] + K[x]))).mod(m)).intValue();
    } else {
        r[x] = 0;
    }
    x++;
}

新しい:

x = 0;
while (x < T) {

//this has been moved from your first while loop
N[x] = input.nextInt();
K[x] = input.nextInt();

if (N[x] >= 3) { 
        r[x] = ((p.nCr(N[x] - 3, K[x]).multiply(p.nCr(N[x] + K[x], N[x] - 1))).divide(BigInteger.valueOf((N[x] + K[x]))).mod(m)).intValue();
    } else {
        r[x] = 0;
    }
    x++;
}
于 2012-05-11T22:07:07.503 に答える
-1

たとえばjvisualvmなどのprofilermを使用して実行し、このクラスを次のように実行してみてください。

-Dcom.sun.management.jmxremote

プロセスにアタッチして、プロファイルを開始します。

于 2012-05-11T22:16:25.833 に答える