結果
| 問題 |
No.3036 Nauclhlt型文字列
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:08:18 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 11,404 bytes |
| コンパイル時間 | 480 ms |
| コンパイル使用メモリ | 72,044 KB |
| 実行使用メモリ | 7,844 KB |
| 最終ジャッジ日時 | 2025-05-14 13:09:55 |
| 合計ジャッジ時間 | 1,287 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | WA * 3 |
| other | WA * 15 |
ソースコード
#include <iostream> // Required for input/output operations (cin, cout)
// Use a namespace to group related constants and functions, avoiding global scope pollution.
namespace RestrictedLucas {
// Define constants using sizeof(char) and basic arithmetic operations.
// This avoids using forbidden digit characters.
struct Constants {
// Basic integer constants
static const long long ONE = sizeof(char); // sizeof(char) is guaranteed to be 1
static const long long ZERO = ONE - ONE; // 0
static const long long TWO = ONE + ONE; // 2
static const long long THREE = TWO + ONE; // 3
static const long long FOUR = TWO + TWO; // 4
static const long long FIVE = FOUR + ONE; // 5
static const long long SIX = THREE + THREE; // 6
// static const long long SEVEN = SIX + ONE; // 7 - defined below for P calculation
static const long long EIGHT = FOUR + FOUR; // 8
// static const long long NINE = EIGHT + ONE; // 9 - unused
static const long long TEN = FIVE + FIVE; // 10
// Constant 64 using bit shift (1 << 6)
static const long long SIXTYFOUR = ONE << SIX; // 64
// Constant 63 (used for sign bit check in 64-bit integers)
static const long long SIXTYTHREE = SIXTYFOUR - ONE; // 63
// Newline character (ASCII value 10)
static const char NEWLINE = static_cast<char>(TEN);
// Unsigned constants needed for constructing the large modulus P
static const unsigned long long uONE = sizeof(char);
static const unsigned long long uTWO = uONE + uONE;
static const unsigned long long uFOUR = uTWO + uTWO;
static const unsigned long long uEIGHT = uFOUR + uFOUR;
static const unsigned long long uTEN = uEIGHT + uTWO; // 10
};
// Global variable to store the modulus P = 1000000007
long long P_MOD;
// Helper function for unsigned multiplication without using the '*' operator.
// Uses the binary method (similar to exponentiation by squaring).
unsigned long long multiply_unsigned(unsigned long long a, unsigned long long b) {
unsigned long long res = Constants::ZERO;
// Loop while b is greater than 0
while (b) {
// Check the least significant bit of b
if (b & Constants::uONE) { // If b is odd
res = res + a; // Add a to the result
}
// Double a (equivalent to a * 2)
a = a + a;
// Halve b (integer division, equivalent to b / 2)
b >>= Constants::uONE; // Right shift by 1
}
return res;
}
// Function to initialize the global modulus P_MOD = 1000000007
// Calculates P without using digit characters or forbidden operators.
void initialize_P_MOD() {
// Calculate powers of 10 using multiply_unsigned
const unsigned long long uHUNDRED = multiply_unsigned(Constants::uTEN, Constants::uTEN); // 100
const unsigned long long uTHOUSAND = multiply_unsigned(uHUNDRED, Constants::uTEN); // 1000
const unsigned long long uMILLION = multiply_unsigned(uTHOUSAND, uTHOUSAND); // 1,000,000
const unsigned long long uBILLION = multiply_unsigned(uMILLION, uTHOUSAND); // 1,000,000,000
// Constant 7
const unsigned long long uSEVEN = Constants::uFOUR + Constants::uTWO + Constants::uONE; // 4 + 2 + 1 = 7
// P = 10^9 + 7
P_MOD = static_cast<long long>(uBILLION + uSEVEN); // 1,000,000,007
}
// Utility function to check if a < b without using '<' operator.
// Uses properties of two's complement representation and bit shifts.
// Assumes 64-bit long long.
bool is_less(long long a, long long b) {
long long diff = a - b;
// Check the sign bit (most significant bit).
// Casting to unsigned long long ensures arithmetic right shift is not used on negative values.
// Right shifting by 63 bits isolates the sign bit for a 64-bit integer.
// Result is 1 if diff is negative (a < b), 0 otherwise.
return ((unsigned long long)diff >> Constants::SIXTYTHREE);
}
// Modular addition: computes (a + b) mod P_MOD without using '%' operator.
long long mod_add(long long a, long long b) {
long long res = a + b;
// If the sum is greater than or equal to P_MOD, subtract P_MOD to bring it into range [0, P_MOD-1].
// This works correctly because if a, b are in [0, P_MOD-1], then a+b is in [0, 2*P_MOD-2].
// So at most one subtraction is needed.
if (!is_less(res, P_MOD)) { // Equivalent to: if (res >= P_MOD)
res = res - P_MOD;
}
return res;
}
// Modular subtraction: computes (a - b) mod P_MOD without using '%' operator.
long long mod_sub(long long a, long long b) {
long long res = a - b;
// If the result is negative, add P_MOD to bring it into range [0, P_MOD-1].
if (is_less(res, Constants::ZERO)) { // Equivalent to: if (res < 0)
res = res + P_MOD;
}
return res;
}
// Modular multiplication: computes (a * b) mod P_MOD without using '*' or '%' operators.
// Uses the binary method (also known as Russian peasant multiplication).
long long mod_mul(long long a, long long b) {
long long res = Constants::ZERO;
// Pre-conditions: Assume a and b are non-negative and already within [0, P_MOD-1].
// This holds true within the matrix exponentiation context where results are always kept modulo P_MOD.
// The loop iterates based on the bits of b. Max iterations is the number of bits in b (e.g., 64).
while (b) { // Loop while b is non-zero
if (b & Constants::ONE) { // Check if the last bit of b is 1 (i.e., if b is odd)
res = mod_add(res, a); // Add a to the result (modulo P_MOD)
}
// Double a (modulo P_MOD). Equivalent to a = (a * 2) % P_MOD
a = mod_add(a, a);
// Halve b (integer division). Equivalent to b = b / 2
b >>= Constants::ONE;
}
return res;
}
// Structure to represent a 2x2 matrix.
struct Matrix {
// The dimension of the matrix (2). Uses sizeof(short), assuming it is 2.
// This is a common assumption in competitive programming environments.
static const int _DIM = sizeof(short);
long long mat[_DIM][_DIM]; // 2x2 matrix storage
// Default constructor
Matrix() {}
// Matrix multiplication: Computes C = this * other (mod P_MOD).
Matrix multiply(Matrix other) {
Matrix result;
int i = Constants::ZERO;
// Loop through rows of the result matrix
while (is_less(i, _DIM)) { // Equivalent to: for(int i = 0; i < _DIM; ++i)
int j = Constants::ZERO;
// Loop through columns of the result matrix
while (is_less(j, _DIM)) { // Equivalent to: for(int j = 0; j < _DIM; ++j)
result.mat[i][j] = Constants::ZERO; // Initialize element to 0
int k = Constants::ZERO;
// Inner loop for dot product calculation
while (is_less(k, _DIM)) { // Equivalent to: for(int k = 0; k < _DIM; ++k)
// Compute term this->mat[i][k] * other.mat[k][j] (mod P_MOD)
long long term = mod_mul(mat[i][k], other.mat[k][j]);
// Add the term to the result element (mod P_MOD)
result.mat[i][j] = mod_add(result.mat[i][j], term);
// Increment inner loop counter
k = k + Constants::ONE; // k++
}
// Increment column loop counter
j = j + Constants::ONE; // j++
}
// Increment row loop counter
i = i + Constants::ONE; // i++
}
return result;
}
};
// Matrix exponentiation: Computes base^exp (mod P_MOD) using exponentiation by squaring.
Matrix matrix_pow(Matrix base, long long exp) {
Matrix result;
// Initialize result matrix to the identity matrix [[1, 0], [0, 1]]
result.mat[Constants::ZERO][Constants::ZERO] = Constants::ONE;
result.mat[Constants::ZERO][Constants::ONE] = Constants::ZERO;
result.mat[Constants::ONE][Constants::ZERO] = Constants::ZERO;
result.mat[Constants::ONE][Constants::ONE] = Constants::ONE;
// Perform exponentiation by squaring
while (exp) { // Loop while exponent is greater than 0
if (exp & Constants::ONE) { // If the current exponent bit is 1 (i.e., exp is odd)
// Multiply result by the current base power: result = result * base
result = result.multiply(base);
}
// Square the base: base = base * base
base = base.multiply(base);
// Halve the exponent (integer division): exp = exp / 2
exp >>= Constants::ONE;
}
return result; // Return the final computed matrix power
}
} // namespace RestrictedLucas
// Main function - entry point of the program
int main() {
// Initialize the global modulus P_MOD = 1000000007
RestrictedLucas::initialize_P_MOD();
// Optimize standard input/output operations by disabling synchronization with C stdio
std::ios_base::sync_with_stdio(false);
// Note: Untie cin from cout (cin.tie(nullptr)) is usually done too, but omitted here for simplicity
// as `nullptr` might require headers or features potentially problematic under constraints.
int T; // Variable to store the number of test cases
std::cin >> T; // Read the number of test cases
int t_count = RestrictedLucas::Constants::ZERO; // Initialize test case counter
// Loop T times to process each test case
while (RestrictedLucas::is_less(t_count, T)) { // Equivalent to: for(t_count=0; t_count < T; ++t_count)
long long N; // Variable to store the input index N for the Lucas sequence
std::cin >> N; // Read N for the current test case
// Define the base matrix M = [[1, 1], [1, 0]]
// This matrix represents the linear recurrence relation L(k+2) = L(k+1) + L(k)
RestrictedLucas::Matrix M;
M.mat[RestrictedLucas::Constants::ZERO][RestrictedLucas::Constants::ZERO] = RestrictedLucas::Constants::ONE;
M.mat[RestrictedLucas::Constants::ZERO][RestrictedLucas::Constants::ONE] = RestrictedLucas::Constants::ONE;
M.mat[RestrictedLucas::Constants::ONE][RestrictedLucas::Constants::ZERO] = RestrictedLucas::Constants::ONE;
M.mat[RestrictedLucas::Constants::ONE][RestrictedLucas::Constants::ONE] = RestrictedLucas::Constants::ZERO;
// Compute M^N using matrix exponentiation. This takes O(log N) matrix multiplications.
RestrictedLucas::Matrix MN = RestrictedLucas::matrix_pow(M, N);
// The N-th Lucas number L(N) can be found using the identity L(N) = F(N-1) + F(N+1),
// where F are Fibonacci numbers.
// It is also known that L(N) = trace(M^N), where trace is the sum of diagonal elements.
// The computed matrix MN = [[F(N+1), F(N)], [F(N), F(N-1)]].
// So, trace(MN) = F(N+1) + F(N-1).
long long LN = RestrictedLucas::mod_add(MN.mat[RestrictedLucas::Constants::ZERO][RestrictedLucas::Constants::ZERO], MN.mat[RestrictedLucas::Constants::ONE][RestrictedLucas::Constants::ONE]);
// Output the computed N-th Lucas number (modulo P_MOD) followed by a newline character.
std::cout << LN << RestrictedLucas::Constants::NEWLINE;
// Increment the test case counter
t_count = t_count + RestrictedLucas::Constants::ONE;
}
// Return 0 to indicate successful program execution.
return RestrictedLucas::Constants::ZERO;
}
qwewe