結果
| 問題 |
No.1443 Andd
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:06:47 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 5,960 bytes |
| コンパイル時間 | 740 ms |
| コンパイル使用メモリ | 90,244 KB |
| 実行使用メモリ | 16,728 KB |
| 最終ジャッジ日時 | 2025-05-14 13:08:30 |
| 合計ジャッジ時間 | 13,929 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 5 TLE * 3 -- * 12 |
ソースコード
#include <iostream> // Provides standard input/output stream objects (cin, cout)
#include <vector> // Provides the vector container
#include <numeric> // Provides numeric algorithms (not strictly needed here but generally useful)
#include <unordered_set> // Provides the unordered_set container (hash set)
#include <bitset> // Provides the bitset container
#include <utility> // Provides std::move
// Define the constant M = 2^10 = 1024 based on the problem constraint A_i < 2^10.
// Values less than M will be handled differently from values >= M.
const int M = 1024;
int main() {
// Optimize standard I/O operations by decoupling C++ streams from C stdio
// and disabling synchronization. This typically speeds up input/output.
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int N; // Number of elements in the sequence A
std::cin >> N;
// Declare a vector to store the sequence A. Use unsigned int because A_i are non-negative.
std::vector<unsigned int> A(N);
// Read N integers into the vector A
for (int i = 0; i < N; ++i) {
std::cin >> A[i];
}
// The state (set of possible values for X) is partitioned into two parts:
// 1. Small values: Values strictly less than M. Stored efficiently in a std::bitset.
// 2. Large values: Values greater than or equal to M. Stored in a std::unordered_set.
// Bitset to track reachable values less than M. Size M represents indices 0 to M-1.
std::bitset<M> current_bs_small;
// Unordered_set (hash set) to track reachable values >= M. Using unsigned int for values.
// The maximum possible value can reach N * max(A_i) ~ 2e4 * 1023 ~ 2e7, which fits in unsigned int.
std::unordered_set<unsigned int> current_set_large;
// Initialize the state. Initially, X=0. Since 0 < M, it belongs to the small set.
current_bs_small[0] = 1; // Mark 0 as reachable
// Iterate through each element A[i] of the sequence, performing the operations.
for (int i = 0; i < N; ++i) {
// Prepare containers for the next state (after the i-th operation).
// These will store the results of applying + A[i] and AND A[i] to the current reachable values.
std::bitset<M> next_bs_small; // Next state's small values
std::unordered_set<unsigned int> next_set_large; // Next state's large values
// Optionally, we could reserve space in next_set_large for potential performance gains,
// e.g., next_set_large.reserve(current_set_large.size() + M); but it's often fine without it.
unsigned int current_A = A[i]; // The current element from sequence A
// --- Process elements from the previous small set (values k_small < M) ---
// Iterate through all possible small values from 0 to M-1.
// A potential optimization for sparse bitsets is to use find_first/find_next,
// but for M=1024, a simple loop is likely sufficient.
for (int k_small = 0; k_small < M; ++k_small) {
if (current_bs_small[k_small]) { // Check if k_small was a reachable value in the previous step
// Option 1: Apply AND operation (k_small & current_A)
unsigned int val_and = k_small & current_A;
// Since k_small < M and current_A < M, the result val_and is guaranteed to be < M.
next_bs_small[val_and] = 1; // Mark this result as reachable in the next small set
// Option 2: Apply ADD operation (k_small + current_A)
unsigned int val_add = k_small + current_A;
if (val_add < M) {
// If the sum is still small, mark it as reachable in the next small set
next_bs_small[val_add] = 1;
} else {
// If the sum becomes large (>= M), insert it into the next large set
next_set_large.insert(val_add);
}
}
}
// --- Process elements from the previous large set (values k_large >= M) ---
// Iterate through each value k_large that was reachable and >= M in the previous step.
for (unsigned int k_large : current_set_large) {
// Option 1: Apply AND operation (k_large & current_A)
unsigned int val_and = k_large & current_A;
// Although k_large might be large, current_A < M = 2^10 has only bits up to index 9 set.
// The AND operation `k_large & current_A` effectively zeros out bits at index 10 and higher.
// Therefore, the result val_and is guaranteed to be <= current_A < M.
next_bs_small[val_and] = 1; // Mark this result as reachable in the next small set
// Option 2: Apply ADD operation (k_large + current_A)
unsigned int val_add = k_large + current_A;
// Since k_large >= M and current_A >= 0, the sum val_add is guaranteed to be >= M.
next_set_large.insert(val_add); // Insert the result into the next large set
}
// Update the current state to the computed next state.
// Using std::move can be more efficient as it avoids copying data if possible.
current_bs_small = std::move(next_bs_small);
current_set_large = std::move(next_set_large);
// Calculate the total number of distinct reachable values after this step.
// It's the sum of the count of set bits in the small set bitset and the size of the large set.
// The problem guarantees this count fits within a 31-bit integer. `size_t` is typically 64-bit, so it's safe.
size_t total_size = current_bs_small.count() + current_set_large.size();
// Output the total size for the current step i (after the i-th operation) followed by a newline.
std::cout << total_size << "\n";
}
return 0; // Indicate successful execution
}
qwewe