HeadHunter 2016プログラマースクールの通信ツアーのタスクの分析パート1

すべての人に良い一日を! 9月30日、 HeadHunter 2016プログラミングスクールへの申し込みの受付終了しました。 この記事では、通信フェーズのタスクを分析したいと思います。 問題を解決するために十数箇所のサイトを訪れなければならなかったことを考えると、私の記事が役に立つことを願っています。 私はプログラミングの経験がほとんどないため、自分のソリューションが唯一の正しいソリューションであるとは主張しません。 私はいつもあなたの批判を聞いてうれしいです!

問題を解決するときは、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 == 0mの最小値を検索します 。 そのような値を選択するには、 forループを使用ます。 そのようなmが見つかるとすぐに、ループを終了します。



solve(BigInteger n、BigInteger m)メソッドは、変数が1ずつnからmに変化するforループを使用してmod(BigInteger n)メソッドを使用して取得したすべての値の合計を計算します。

BigIntegerを使用した古いソリューション
 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つのボリュームタスクがあり、要素を列挙するロジックを解析する必要があります。 次の出版物で残りのタスクを分析します。



All Articles