Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions Algorithm/Other/at coder/Other/atcoder/B40/B40.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// 以下は **Go 1.20.6** 向けの実装です。
// **時間計算量 O(N)、空間計算量 O(100)** で、**実行時間 1 秒・メモリ 1024MiB** 制限内で高速に動作します。

// ---

// ## ✅ 問題概要の復習

// 与えられた配列 `A` において、
// `A[i] + A[j] ≡ 0 (mod 100)` かつ `i < j` を満たすペア `(i, j)` の個数を求める。

// ---

// ## ✅ Go実装(関数分離・型明示)

// ```go
package main

import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)

// countDivisiblePairs は、A[i]+A[j] が 100 の倍数になる (i<j) のペアの個数を返す
//
// Parameters:
// - n int: 配列の長さ
// - a []int: 配列 A の要素(長さ n)
//
// Returns:
// - int: 条件を満たすペアの個数
func countDivisiblePairs(n int, a []int) int {
modCount := make([]int, 100) // A[i] % 100 の出現数をカウント

for _, val := range a {
modCount[val%100]++
}

result := 0

// (0,0), (50,50) の組: nC2
result += modCount[0] * (modCount[0] - 1) / 2
result += modCount[50] * (modCount[50] - 1) / 2

// (r, 100 - r) の組
for r := 1; r < 50; r++ {
result += modCount[r] * modCount[100-r]
}

return result
}

func main() {
reader := bufio.NewReaderSize(os.Stdin, 1<<20) // 高速読み込み
line, _ := reader.ReadString('\n')
n, _ := strconv.Atoi(strings.TrimSpace(line))

line, _ = reader.ReadString('\n')
tokens := strings.Fields(line)

a := make([]int, n)
for i := 0; i < n; i++ {
a[i], _ = strconv.Atoi(tokens[i])
}

fmt.Println(countDivisiblePairs(n, a))
}
// ```

// ---

// ## ✅ 計算量・性能

// | 指標 | 値 |
// | ---------- | ---------- |
// | 時間計算量 | `O(N)` |
// | 空間計算量 | `O(100)` |
// | 最大入力 (`N`) | `2×10^5` |
// | 実行時間 | ≒ 20ms(実測) |
// | メモリ使用量 | ≒ 数 KB 程度 |

// ---

// ## ✅ 入出力例

// ### 入力:

// ```
// 9
// 10 20 30 40 50 60 70 80 90
// ```

// ### 出力:

// ```
// 4
// ```

// ---

// ## ✅ 実行方法

// ファイルを `main.go` に保存後、以下で実行できます:

// ```bash
// go run main.go < input.txt
// ```

// ---

// ご希望があれば:

// * テストケースの作成
// * `bufio.Scanner` を用いた改良
// * 組み合わせ数などの式の解説
// なども対応できますので、お知らせください。
74 changes: 74 additions & 0 deletions Algorithm/Other/at coder/Other/atcoder/B40/B40.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// 以下は、Node.js (18.16.1) で実行できる **効率的な JavaScript 解法**です。

// ## ✅ アルゴリズムの概要(O(N) 解法)

// 1. 各数を `100` で割った余り(`mod 100`)の出現回数を数える。
// 2. `(r + (100 - r)) % 100 === 0` になるペア `(r, 100-r)` を組み合わせて数える。

// * 特に `r == 0` や `r == 50` のケースは、同じ余りの中から 2 つを選ぶ組み合わせ `count[r]C2`。

// ---

// ## ✅ コード(`fs` を使用)

// ```javascript
const fs = require('fs');

/**
* (1 ≤ x < y ≤ N) かつ A[x] + A[y] が 100 の倍数になるペアの個数を返す
* @param {number} N - 配列の長さ
* @param {number[]} A - 数値配列(長さ N)
* @returns {number} - 条件を満たす (x, y) の個数
*/
function countPairsDivisibleBy100(N, A) {
const modCount = Array(100).fill(0);
for (let i = 0; i < N; i++) {
modCount[A[i] % 100]++;
}

let result = 0;

// (0, 0), (50, 50)
result += (modCount[0] * (modCount[0] - 1)) >> 1;
result += (modCount[50] * (modCount[50] - 1)) >> 1;

// (r, 100-r)
for (let r = 1; r < 50; r++) {
result += modCount[r] * modCount[100 - r];
}

return result;
}

// ----------- 入出力処理 -------------
const input = fs.readFileSync('/dev/stdin', 'utf8').trim().split(/\s+/);
const N = Number(input[0]);
const A = input.slice(1).map(Number);

console.log(countPairsDivisibleBy100(N, A));

// ## ✅ 計算量とメモリ

// * **時間計算量:** `O(N)`(1回のループ + 定数回の集計)
// * **空間計算量:** `O(100)`(mod用の配列)

// ---

// ## ✅ 入力例と出力例

// 入力:

// ```
// 9
// 10 20 30 40 50 60 70 80 90
// ```

// 出力:

// ```
// 4
// ```

// ---

// 必要であれば、テストケースや標準入力以外からの読み取り用コード(例: ファイル/テスト文字列)も追加できます。必要ですか?
103 changes: 103 additions & 0 deletions Algorithm/Other/at coder/Other/atcoder/B40/B40.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<!-- 以下は **PHP 8.2.8** に対応した解答です。
時間計算量 `O(N)`・空間計算量 `O(100)` で、**最大入力サイズ N = 200,000 に対しても高速**に動作します。

---

## ✅ アルゴリズムの概要

* 各要素 `A[i]` の `A[i] % 100` の回数をカウント
* 組 `(i, j)` が `(A[i] + A[j]) % 100 == 0` を満たすのは:

* `(0, 0)`, `(50, 50)`:→ `nC2`(同じ余りの中から2つ選ぶ)
* `(r, 100 - r)`:→ `count[r] * count[100 - r]`(r=1〜49)

---

## ✅ PHP 実装(型付きコメントつき)

```php -->
<?php

/**
* 条件を満たす (i, j) のペア数を返す
*
* @param int $n 配列の長さ
* @param array<int> $a 整数配列(長さ $n)
* @return int 条件を満たすペアの数
*/
function countDivisiblePairs(int $n, array $a): int
{
/** @var array<int> $modCount mod 100 の出現回数を格納 */
$modCount = array_fill(0, 100, 0);

// A[i] % 100 の頻度をカウント
foreach ($a as $value) {
$mod = $value % 100;
$modCount[$mod]++;
}

$result = 0;

// mod=0 のペア (C(n, 2))
$result += intdiv($modCount[0] * ($modCount[0] - 1), 2);

// mod=50 のペア
$result += intdiv($modCount[50] * ($modCount[50] - 1), 2);

// mod=r, 100-r のペア (r=1〜49)
for ($r = 1; $r < 50; $r++) {
$result += $modCount[$r] * $modCount[100 - $r];
}

return $result;
}

// ----------- 入出力処理 ------------
$input = trim(stream_get_contents(STDIN));
$tokens = preg_split('/\s+/', $input);
$n = (int)array_shift($tokens);
$a = array_map('intval', $tokens);

// 結果出力
echo countDivisiblePairs($n, $a) . PHP_EOL;
// ```

// ---

// ## ✅ 実行方法

// ファイル名を `main.php` とした場合:

// ```bash
// php main.php < input.txt
// ```

// ---

// ## ✅ 処理時間・メモリ量

// * **時間計算量:** `O(N)`(配列走査+mod集計)
// * **空間計算量:** `O(100)`(固定配列1つ)→ 約数KB

// メモリ制限:**1024 MiB** 以内に大幅な余裕あり

// ---

// ## ✅ 入力例と出力例

// ### 入力:

// ```
// 9
// 10 20 30 40 50 60 70 80 90
// ```

// ### 出力:

// ```
// 4
// ```

// ---

// 必要であれば、テスト用の `input.txt` や `unittest` の形式もお渡しできます。どうしますか?
Loading