結果
| 問題 |
No.1871 divisXor
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:03:16 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 8,819 bytes |
| コンパイル時間 | 1,002 ms |
| コンパイル使用メモリ | 90,800 KB |
| 実行使用メモリ | 132,300 KB |
| 最終ジャッジ日時 | 2025-05-14 13:05:55 |
| 合計ジャッジ時間 | 7,902 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | TLE * 2 |
| other | TLE * 29 |
ソースコード
#include <iostream>
#include <vector>
#include <numeric>
#include <map>
// Use __int128 for intermediate calculations in Miller-Rabin power function to avoid overflow with large moduli
typedef long long ll;
/*
* Miller-Rabin Primality Test for 64-bit integers
* Uses __int128 for modular exponentiation intermediate products.
*/
// Modular exponentiation: (base^exp) % modulus
ll power(ll base, ll exp, ll modulus) {
ll res = 1;
base %= modulus;
while (exp > 0) {
if (exp % 2 == 1) res = (__int128)res * base % modulus;
base = (__int128)base * base % modulus;
exp /= 2;
}
return res;
}
// Checks if 'a' is a witness that 'n' is composite.
// n is the number to test, a is the base, d and s are such that n-1 = d * 2^s with d odd.
bool check_composite(ll n, ll a, ll d, int s) {
ll x = power(a, d, n); // Calculate a^d % n
// If a^d % n = 1 or a^d % n = n-1, n might be prime.
if (x == 1 || x == n - 1)
return false;
// Check for a^(d * 2^r) % n == n-1 for r from 1 to s-1
for (int r = 1; r < s; r++) {
x = (__int128)x * x % n; // Square x modulo n
if (x == n - 1)
return false; // Might be prime
}
// If none of the conditions are met, n is definitely composite.
return true;
}
// Deterministic Miller-Rabin primality test for n < 2^64
bool is_prime(ll n) {
if (n < 2) return false; // Primes are >= 2
// Find d and s such that n-1 = d * 2^s where d is odd
int s = 0;
ll d = n - 1;
while ((d & 1) == 0) { // While d is even
d >>= 1; // Divide d by 2
s++; // Increment s
}
// Use a standard set of bases proven sufficient for deterministic check for n < 2^64
// Bases from https://miller-rabin.appspot.com/
// Using fewer bases {2, 7, 61} is sufficient for n < 2^32, but use larger set for safety up to 2^64.
for (ll a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
if (n == a) return true; // Handle cases where n is one of the bases (which are prime)
if (a % n == 0) continue; // Base 'a' is a multiple of 'n', provides no info
// Check if 'a' is a witness for compositeness of 'n'
if (check_composite(n, a, d, s))
return false; // Found a witness, n is composite
}
// If no witness found after checking all required bases, n is prime for n < 2^64
return true;
}
/*
* Precomputation of sum of divisors function f(k) = sigma_1(k)
*/
// K_limit is the search limit for k in strategies 5' and 6.
// MAXK is the array size for precomputation, needs to be at least 2*K_limit + 1.
const int K_limit = 2000000;
const int MAXK = 4000005;
std::vector<ll> f_values(MAXK); // Stores f(k) for k < MAXK
// Map to quickly find the smallest k for a given f(k) value.
std::map<ll, ll> f_to_k;
// Precompute f(k) values using a sieve-like method to find prime factorizations
void precompute_f() {
// Sieve to find the smallest prime factor (SPF) for each number up to MAXK-1
std::vector<int> min_prime_factor(MAXK);
std::vector<int> primes; // List of prime numbers found
for (int i = 2; i < MAXK; ++i) {
if (min_prime_factor[i] == 0) { // If i is prime
min_prime_factor[i] = i;
primes.push_back(i);
}
// Mark multiples of primes found so far
for (int p : primes) {
// Optimization: If p > SPF[i], then i*p will be marked later by SPF[i].
if (p > min_prime_factor[i] || (ll)i * p >= MAXK) break;
min_prime_factor[i * p] = p;
}
}
// Base case f(1) = 1
f_values[1] = 1;
if (f_to_k.find(1) == f_to_k.end()) {
f_to_k[1] = 1;
}
// Compute f(k) for k from 2 to MAXK-1 using the multiplicative property
// f(k) = f(p1^e1) * f(p2^e2) * ... where k = p1^e1 * p2^e2 * ...
// f(p^e) = 1 + p + p^2 + ... + p^e
for (int k = 2; k < MAXK; ++k) {
int current_k = k;
ll total_f = 1; // Initialize f(k)
while (current_k > 1) { // While there are prime factors left
int p = min_prime_factor[current_k]; // Get smallest prime factor
ll p_power = 1; // Holds p^i
ll f_p_e = 0; // Holds sum of divisors for p^e
// Calculate f(p^e) = 1 + p + ... + p^e
while (current_k > 0 && current_k % p == 0) {
f_p_e += p_power; // Add p^i to the sum
p_power *= p; // Update p_power to p^(i+1)
current_k /= p; // Divide out the factor p
}
f_p_e += p_power; // Add the last term p^e
total_f *= f_p_e; // Update total_f using multiplicative property
}
f_values[k] = total_f; // Store computed f(k)
// Store the smallest k found for this value of f(k) in the map
if (f_values[k] >= 0 && f_to_k.find(f_values[k]) == f_to_k.end()) {
f_to_k[f_values[k]] = k;
}
}
}
int main() {
// Faster I/O
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
// Perform precomputation
precompute_f();
ll N;
std::cin >> N; // Read input N
// Handle N=0: No solution possible because sum of positive integers must be positive.
if (N == 0) {
std::cout << -1 << std::endl;
return 0;
}
// Handle N=1: Solution A=(1) works. f(1)=1. Sum = 1 < 2*1.
if (N == 1) {
std::cout << 1 << std::endl; // M=1
std::cout << 1 << std::endl; // A_1=1
return 0;
}
/*
* Try strategies to find sequence A.
*/
// Strategy 2: If N-1 is prime (for N >= 2), A=(N-1) is a solution.
// f(N-1) = (N-1)+1 = N. Sum = N-1. N-1 < 2N is true for N >= 1.
if (N >= 2) {
ll N_minus_1 = N - 1;
// Check N-1 > 0 and primality using Miller-Rabin
if (N_minus_1 > 0 && is_prime(N_minus_1)) {
std::cout << 1 << std::endl; // M=1
std::cout << N_minus_1 << std::endl; // A_1 = N-1
return 0;
}
}
// Strategy 3: Check if N = f(k) for some small k using the precomputed map.
// If found, A=(k) is a solution. f(k)=N. Sum=k. k <= f(k)=N. For N >= 1, k < 2N.
if (f_to_k.count(N)) {
ll k = f_to_k[N];
std::cout << 1 << std::endl; // M=1
std::cout << k << std::endl; // A_1 = k
return 0;
}
// Strategy 4: Check if f(k) = N ^ 1 for some small k > 1.
// If found, A=(1, k) is a solution. f(1) ^ f(k) = 1 ^ (N^1) = N. Sum = 1+k. Need 1+k < 2N.
ll N_xor_1 = N ^ 1;
if (f_to_k.count(N_xor_1)) {
ll k = f_to_k[N_xor_1];
if (k > 1) { // k must be distinct from 1.
// Check sum condition. Long long is sufficient as 2*N fits.
if (1 + k < 2 * N) {
std::cout << 2 << std::endl; // M=2
std::cout << 1 << " " << k << std::endl; // A = (1, k)
return 0;
}
}
}
// Strategy 5': Find smallest k > 1 such that f(k) ^ f(2k) = N ^ 1.
// If found, A=(1, k, 2k) is a solution. f(1)^f(k)^f(2k) = 1 ^ (N^1) = N.
// Sum = 1+k+2k = 1+3k. Need 1+3k < 2N.
for (ll k = 2; k <= K_limit; ++k) {
// Ensure 2*k is within precomputed range
if (2*k >= MAXK) break;
ll fk = f_values[k];
ll f2k = f_values[2*k];
// Check if XOR matches target N^1
if ((fk ^ f2k) == N_xor_1) {
// Check sum condition. Long long is sufficient.
if (1 + 3 * k < 2 * N) {
std::cout << 3 << std::endl; // M=3
std::cout << 1 << " " << k << " " << 2 * k << std::endl; // A = (1, k, 2k)
return 0;
}
}
}
// Strategy 6: Find smallest k1 > 1, then smallest k2 > 1 such that f(k1) ^ f(k2) = N.
// If found, A=(k1, k2) is a solution. f(k1)^f(k2) = N. Sum = k1+k2. Need k1+k2 < 2N.
for (ll k1 = 2; k1 <= K_limit; ++k1) {
ll fk1 = f_values[k1];
ll V = N ^ fk1; // Target value for f(k2)
// Look up V in the map to find a suitable k2
if (f_to_k.count(V)) {
ll k2 = f_to_k[V];
// Ensure k2 > 1 and k1, k2 are distinct
if (k2 > 1 && k1 != k2) {
// Check sum condition. Long long is sufficient.
if (k1 + k2 < 2 * N) {
std::cout << 2 << std::endl; // M=2
std::cout << k1 << " " << k2 << std::endl; // A = (k1, k2)
return 0;
}
}
}
}
// If none of the strategies provided a solution
std::cout << -1 << std::endl;
return 0;
}
qwewe