問題を解決するときは、Javaプログラミング言語が使用されます。
この記事はユーザーのコメントの助けを借りて修正されています。最初の問題を解決するために1つのサイクルが使用されます。自然数の階乗を計算するとき
タスク1
数値が文字で置き換えられる等式が与えられます:rqr + rqq = sqr。 異なる数字が異なる文字に対応する場合、彼が持っている解決策をいくつ見つけます(数字の先頭のゼロは存在しません)。
この問題を解決するには、2つの方法を選択できます。3つのネストされたforループを使用して「額」を解決するか、式を変換して2つのネストされたforループのみを使用します。
2番目の方法を選択します。 問題の状態を表す文字は数字です。つまり、それぞれが0から9まで変化します 。 10進数システムでのcislの表現を思い出して、式を次の形式に変換します: s = 2r + 0.11q 。 次に、問題を解決するためのコードは次のようになります。
古い決定
public class FirstTask { public static void main(String[] args){ int count = 0; for (int q = 0; q < 10; q++){ for (int r = 1; r < 10; r++){ if ((r != q)){ double s = 2 * r + 0.11 * q; if (s % 1 == 0 && s != 0 && s < 10) count++; } } } System.out.println("count is " + count); } }
問題の状態は、先行ゼロがないはずであると述べており、これに基づいて、変数の初期値が選択されました。 s変数の場合、条件s%1 == 0を正しく満たすためにdouble型を使用する必要があります。 このプログラムは、次のアイデンティティを考慮します。
101 + 100 = 201.0 202 + 200 = 402.0 303 + 300 = 603.0 404 + 400 = 804.0 count is 4
q = 0を考慮すると、サイクルは1つだけになります。
public class FirstTask { public static void main(String[] args){ int count = 0; for (int r = 1; 2 * r < 10; r++) count++; System.out.println("count is " + count); } }
タスク2
mのような最小数m! 10を余りで割った値-m = 5(5!= 120)です。 同様に、最小数mはm! 25を余りで割った値-これはm = 10です。 一般的なケースでは、関数s(n)の値は、m! nで割り切れます。
すべてのn∈[M、N]に対して関数S(M、N)= ∑s(n)を定義します。 たとえば、S(6、10)= 3 + 7 + 4 + 6 + 5 =25。S(2300000、2400000)を見つけます。
タスクをいくつかの段階に分けます。 自然数の階乗を計算するメソッド(メソッドfactorial(BigInteger m) )、問題の条件を満たす値mを計算するメソッド(method mod(BigInteger n) )、および関数Sの値を計算するメソッド(M、N) ( solve(BigInteger method n、BigInteger m) )。
問題の状態では、関数S(2300000、2400000)の値を見つける必要があることに注意してください。引数の階乗は大きな数になるため、すべての数値変数にはBigInteger型を使用します(そうでない場合、計算は正しくありません)。
ループを使用して階乗(BigInteger m)メソッドを実装します。現在の変数retに forループ変数を乗算し、ループのすべての反復が完了するまで結果を代入します。
mod(BigInteger n)メソッドは、タスクの条件を満たすfactorial(m)%n == 0のmの最小値を検索します 。 そのような値を選択するには、 forループを使用します。 そのようなmが見つかるとすぐに、ループを終了します。
solve(BigInteger n、BigInteger m)メソッドは、変数が1ずつnからmに変化するforループを使用してmod(BigInteger n)メソッドを使用して取得したすべての値の合計を計算します。
BigIntegerを使用した古いソリューション
問題S(6、10)の条件で、例としてプログラムをテストします。
Sのプログラム実行の結果(2300000、2400000) (タイプlongが使用されました:
public class SecondTask { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BigInteger n = BigInteger.valueOf(Integer.parseInt(br.readLine())); BigInteger m = BigInteger.valueOf(Integer.parseInt(br.readLine())); solve(n,m); } public static BigInteger factorial(BigInteger n) { BigInteger res = BigInteger.ONE; if (n.intValue() == 0 || n.intValue() == 1) return res; else { for (BigInteger i = BigInteger.ONE; i.compareTo(n) <= 0; i = i.add(BigInteger.ONE)) { res = res.multiply(i); } } return res; } public static BigInteger s(BigInteger n) { BigInteger res = BigInteger.ZERO; for (BigInteger m = BigInteger.ZERO; m.compareTo(n) <= 0; m = m.add(BigInteger.ONE)) { System.out.println("m = " + m); if ((factorial(m)).mod(n).equals(BigInteger.ZERO)) { res = m; break; } } return res; } public static BigInteger solve(BigInteger N, BigInteger M){ BigInteger res = BigInteger.ZERO; for (BigInteger i = N; i.compareTo(M) <= 0; i = i.add(BigInteger.ONE)){ BigInteger m = s(i); res = res.add(m); } return res; }
問題S(6、10)の条件で、例としてプログラムをテストします。
6 10 25
Sのプログラム実行の結果(2300000、2400000) (タイプlongが使用されました:
2300000 2400000 6596625
この問題の解決策は、 コメント内のアルゴリズムを使用します 。
public class SecondTask { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); int m = Integer.parseInt(br.readLine()); Date startSolve = new Date(); solve(n, m); Date finishSolve = new Date(); long solveTime = finishSolve.getTime() - startSolve.getTime(); System.out.println("solveTime is " + solveTime + " ms"); } public static int s(int n) { TreeMap<Integer, Integer> treemap = new TreeMap<Integer, Integer>(); int i = 2, count = 1; while (i <= n){ if (n % i == 0){ if (treemap.containsKey(i)){ count++; treemap.put(i, count); } else { count = 1; treemap.put(i, count); } n = n / i; i--; } i++; } int p = treemap.lastKey(), k = treemap.get(treemap.lastKey()), m = 0; if (k > p){ do k--; while(k > p); m = k * p; } else m = k * p; return m; } public static int solve(int n, int m){ int res = 0; for (int i = n; i <= m; i++) res += s(i); System.out.println(res); return res; } }
問題S(6、10)の条件で、例としてプログラムをテストします。
6 10 25 solveTime is 0 ms
Sのプログラムの結果(2300000、2400000) :
2300000 2400000 1796256390 solveTime is 130854 ms
タスク3
1 <a <6および1 <b <6のすべての可能な数a bを考慮します。
22 = 4、23 = 8、24 = 16、25 = 32 32 = 9、33 = 27、34 = 81、35 = 243 42 = 16、43 = 64、44 = 256、45 = 1024、52 = 25、 53 = 125、54 = 625、55 = 3125。 繰り返しを削除すると、15の異なる数値が得られます。 2 <a <135および2 <b <136の異なる数a bはいくつですか?
数値を累乗するために、 Math.pow(x、y)メソッドを使用します(なぜ車輪を再発明するのですか?)。 ただし、このメソッドを使用する場合は、すべての数値変数がdouble型である必要があります。
2つのコレクションを使用して問題を解決します。ArrayListを使用してb要素を追加し 、 HashSetを使用してコレクションからすべての繰り返し要素を削除します。
public class ThirdTask { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("type the interval for a"); double a1 = Long.parseLong(br.readLine()); double a2 = Long.parseLong(br.readLine()); System.out.println("type the interval for b"); double b1 = Long.parseLong(br.readLine()); double b2 = Long.parseLong(br.readLine()); pow(a1, a2, b1, b2); } public static ArrayList<Double> pow(double a1, double a2, double b1, double b2){ ArrayList<Double> arr = new ArrayList<>(); for (double i = a1 + 1; i < a2; i++){ for (double j = b1 + 1; j < b2; j++){ arr.add(Math.pow(i,j)); } } System.out.println("arr size is " + arr.size()); HashSet<Double> list = new HashSet<Double>(arr); System.out.println("now arr size is " + list.size()); return arr; } }
1 <a <6および1 <b <6のプログラムのテスト:
type the interval for a 1 6 type the interval for b 1 6 arr size is 16 now arr size is 15
2 <a <135および2 <b <136のプログラムの結果:
type the interval for a 2 135 type the interval for b 2 136 arr size is 17556 now arr size is 16640
この記事は非常に大規模であり、さらに2つのボリュームタスクがあり、要素を列挙するロジックを解析する必要があります。 次の出版物で残りのタスクを分析します。