Modular Division of Large Numbers
This solution demonstrates how to perform division operations with large numbers under a specific modulus using Fermat's Little Theorem. The approach converts string representations of numbers into numerical arrays and applies modular arithmetic properties.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MOD = 19260817;
int digitsA[10100];
int digitsB[10100];
char inputA[10100];
char inputB[10100];
int startA, startB;
int lengthA, lengthB;
long long numX, numY;
long long fastPower(long long base, long long exponent) {
long long result = 1;
for (; exponent; exponent >>= 1, base = base * base % MOD)
if (exponent & 1) result = result * base % MOD;
return result % MOD;
}
void processNumberA() {
long long value = 0;
for (int i = startA; i <= startA + 8; i++)
value = value * 10 + digitsA[i];
value %= MOD;
for (int i = startA + 8; i >= startA; i--) {
int digit = value % 10;
value /= 10;
digitsA[i] = digit;
}
for (int i = 0; i <= 8; i++)
if (digitsA[startA + i] != 0) {
startA += i;
break;
}
}
void processNumberB() {
long long value = 0;
for (int i = startB; i <= startB + 8; i++)
value = value * 10 + digitsB[i];
value %= MOD;
for (int i = startB + 8; i >= startB; i--) {
int digit = value % 10;
value /= 10;
digitsB[i] = digit;
}
for (int i = 0; i <= 8; i++)
if (digitsB[startB + i] != 0) {
startB += i;
break;
}
}
int main() {
scanf("%s", inputA);
scanf("%s", inputB);
lengthA = strlen(inputA);
lengthB = strlen(inputB);
for (int i = 0; i < lengthA; i++)
digitsA[i] = inputA[i] - '0';
for (int i = 0; i < lengthB; i++)
digitsB[i] = inputB[i] - '0';
while (lengthA - startA >= 10) processNumberA();
while (lengthB - startB >= 10) processNumberB();
for (int i = startA; i < lengthA; i++)
numX = numX * 10 + digitsA[i];
for (int i = startB; i < lengthB; i++)
numY = numY * 10 + digitsB[i];
numX %= MOD;
numY %= MOD;
if (numX == 0) {
puts("0");
return 0;
}
if (numY == 0) {
puts("Division by zero!");
return 0;
}
long long modularInverse = fastPower(numY, MOD - 2);
long long result = (modularInverse * numX) % MOD;
printf("%lld", result);
return 0;
}</algorithm></cstring></cstdio></iostream>
The solution leverages modular arithmetic properties and Fermat's Little Theorem to handle division with large numbers. The key insight is that division under modulo can be transformed into multiplication by the modular inverse.
Coprime Number Pairs in Range
This program counts the number of coprime pairs within a specified range. The solution iterates through possible pairs and uses the Euclidean algorithm to determine if two numbers are coprime.
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
int greatestCommonDivisor(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
int main() {
int testCases;
cin >> testCases;
while (testCases--) {
long long left, right;
cin >> left >> right;
int coprimeCount = 0;
for (long long num2 = left; num2 <= right; ++num2) {
bool foundCoprime = false;
for (long long num1 = num2; num1 >= left; --num1) {
if (greatestCommonDivisor(num1, num2) == 1) {
foundCoprime = true;
coprimeCount++;
break;
}
}
if (!foundCoprime) continue;
}
cout << coprimeCount << endl;
}
return 0;
}</numeric></algorithm></vector></iostream>
Although straightforward, this approach has a time complexity of O(n^2) which makes it inefficient for large ranges. For competitive programming, more optimized solutions using inclusion-exclusion principle or Möbius function would be preferable.
Prime Difference Range Counter
This solution counts numbers in a range [n, m] that can be expressed as x + p, where x is in the range and p is a prime number. It uses the Sieve of Eratosthenes to generate primes and marks composite numbers accordingly.
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
bool isComposite[1000005];
int primes[6000], primeCount = 0;
void generatePrimes() {
for (int i = 2; i <= 800; i++)
if (!isComposite[i]) {
primes[++primeCount] = i;
for (int j = i * i; j <= 800; j += i)
isComposite[j] = true;
}
for (int i = 801; i <= 50000; i++)
for (int j = 1; j <= primeCount; j++) {
if (i % primes[j] == 0) break;
if (primes[j] * primes[j] >= i) {
primes[++primeCount] = i;
break;
}
}
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
generatePrimes();
memset(isComposite, 0, sizeof(isComposite));
for (int k = 1; k <= primeCount && primes[k] <= sqrt(m); k++) {
int square = primes[k] * primes[k];
if (square < n) square = n / primes[k] * primes[k];
if (square < n) {
if (square <= m - primes[k]) square += primes[k];
else continue;
}
for (; square <= m;) {
isComposite[square - n] = true;
if (square == primes[k]) isComposite[square - n] = false;
if (square <= m - primes[k]) square += primes[k];
else break;
}
}
if (n == 1) isComposite[0] = true;
int result = 0;
for (int i = 0; i <= m - n; i++)
if (!isComposite[i]) result++;
cout << result;
return 0;
}</cstring></cmath></iostream></cstdio>
The algorithm efficiently marks numbers that can be expressed as the sum of another number in the range and a prime. By leveraging the Sieve of Eratosthenes, it reduces the problem to counting unmarked numbers in the specified range.
Prime Factor Combination Counter
This program calculates the number of possible combinations based on the prime factors of a quotient. It first checks divisibility and then counts distinct prime factors to determine the number of valid combinations.
#include <iostream>
using namespace std;
int main() {
int x, y;
cin >> x >> y;
if (y % x != 0) {
cout << 0;
return 0;
}
int quotient = y / x;
int factor = 2;
int result = 1;
while (quotient != 1) {
while (quotient % factor != 0) factor++;
while (quotient % factor == 0) quotient /= factor;
factor++;
result *= 2;
}
cout << result;
return 0;
}</iostream>
The solution factors the quotient of y divided by x and uses the count of distinct prime factors to determine the number of possible combinations. Each distinct prime factor doubles the number of possible combinations since each can either be included or excluded.
Maximum LCM Sequence Finder
This program finds the longest sequence of numbers whose least common multiple (LCM) does not exceed a given limit. It sorts the input and builds the sequence by including numbers as long as the LCM constraint is satisfied.
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <cmath>
using namespace std;
long long greatestCommonDivisor(long long a, long long b) {
while (b != 0) {
long long temp = b;
b = a % b;
a = temp;
}
return a;
}
long long leastCommonMultiple(long long a, long long b) {
return a / greatestCommonDivisor(a, b) * b;
}
int main() {
int n, m;
cin >> n >> m;
vector<long long=""> numbers(n);
for (int i = 0; i < n; ++i) {
cin >> numbers[i];
}
sort(numbers.begin(), numbers.end());
vector<int> optimalSequence;
long long currentLCM = 1;
for (int i = 0; i < n; ++i) {
if (leastCommonMultiple(currentLCM, numbers[i]) <= m) {
currentLCM = leastCommonMultiple(currentLCM, numbers[i]);
optimalSequence.push_back(i + 1);
} else {
break;
}
}
cout << currentLCM << " " << optimalSequence.size() << endl;
for (int index : optimalSequence) {
cout << index << " ";
}
cout << endl;
return 0;
}</int></long></cmath></numeric></algorithm></vector></iostream>
The algorithm efficiently builds a sequence by maintaining the current LCM and checking if adding the next number would exceed the limit. Sorting the input beforehand helps in finding the optimal sequence more efffectively.
Sequence Generator Finder
This solution attempts to find a "generator" number for a given sequence, which can reach all other numbers through a series of addition operations involving divisors. The algorithm checks possible starting values and their reachability.
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <cmath>
using namespace std;
vector<int> getDivisors(int number) {
vector<int> divisors;
for (int i = 2; i <= sqrt(number); ++i) {
if (number % i == 0) {
divisors.push_back(i);
if (i != number / i) {
divisors.push_back(number / i);
}
}
}
sort(divisors.begin(), divisors.end());
return divisors;
}
int findGenerator(const vector<int>& sequence) {
int minValue = *min_element(sequence.begin(), sequence.end());
int start = minValue;
const int MAX_ITERATIONS = 1000000;
while (MAX_ITERATIONS--) {
unordered_set<int> reachable;
reachable.insert(start);
bool allReachable = true;
for (int num : sequence) {
if (reachable.count(num)) continue;
vector<int> divisors = getDivisors(num);
bool reachableFromStart = false;
for (int divisor : divisors) {
int candidate = start + (num - (num % divisor)) / divisor * divisor - num;
if (candidate >= 0 && candidate % divisor == 0 && reachable.count(start + candidate / divisor)) {
reachableFromStart = true;
break;
}
}
if (!reachableFromStart) {
allReachable = false;
break;
}
}
if (allReachable) return start;
start++;
}
return -1;
}
int main() {
int testCases;
cin >> testCases;
while (testCases--) {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
cout << findGenerator(a) << endl;
}
return 0;
}</int></int></int></int></int></int></cmath></algorithm></unordered_set></vector></iostream>
The solution searches for a starting value that can reach all elements in the sequence through operations involving divisors. While conceptually interesting, the implementation may have limitations for certain input cases and could benefit from further optimization.