Mathematical Function Analysis
For the first problem, we need to compute a sum based on a specific function f(x). The key insight is recognizing that f(x) = y when the least common multiple of numbers 1 through y-1 divides x, but y does not divide x.
Using the inclusion-exclusion principle, we can calculate the count of numbers satisfying these conditions. The maximum possible value of f(x) is limited since the LCM grows rapidly.
#include <iostream>
#include <vector>
using namespace std;
const long long MAX_LIMIT = 1e16;
const int MOD = 1e9 + 7;
long long compute_gcd(long long a, long long b) {
return b ? compute_gcd(b, a % b) : a;
}
long long compute_lcm(long long a, long long b) {
return a * b / compute_gcd(a, b);
}
vector<long long=""> precompute_lcms() {
vector<long long=""> lcms(1, 1);
for (int i = 2; lcms.back() <= MAX_LIMIT; i++) {
lcms.push_back(compute_lcm(lcms.back(), i));
}
return lcms;
}
long long solve_math_problem(long long n, const vector<long long="">& lcms) {
long long result = 0;
for (int i = 1; i < lcms.size() && lcms[i-1] <= n; i++) {
long long term = i * (n / lcms[i-1] - n / lcms[i]);
result = (result + term) % MOD;
}
return result;
}
int main() {
vector<long long=""> lcms = precompute_lcms();
int test_cases;
cin >> test_cases;
while (test_cases--) {
long long n;
cin >> n;
cout << solve_math_problem(n, lcms) << endl;
}
return 0;
}
</long></long></long></long></vector></iostream>
Matrix Deletion Strategy
The second problem involves maximizing the score when deleting rows and columns from a matrix. The key observation is that row and column deletions don't affect eachother's relative priorities, allowing us to handle them separately.
We use priority queues to track the maximum possible sums when deleting rows or columns, then combine these results while accounting for the penalty when positions are deleted twice.
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int MAX_SIZE = 1005;
const int MAX_DELETES = 1e6 + 5;
int rows, cols, max_deletions, penalty;
vector<vector>> matrix;
vector<long long=""> row_scores, col_scores;
void compute_row_scores() {
priority_queue<long long=""> pq;
for (int i = 0; i < rows; i++) {
long long sum = 0;
for (int j = 0; j < cols; j++) {
sum += matrix[i][j];
}
pq.push(sum);
}
row_scores.resize(max_deletions + 1);
for (int i = 1; i <= max_deletions; i++) {
long long top = pq.top(); pq.pop();
row_scores[i] = row_scores[i-1] + top;
pq.push(top - (long long)cols * penalty);
}
}
void compute_col_scores() {
priority_queue<long long=""> pq;
for (int j = 0; j < cols; j++) {
long long sum = 0;
for (int i = 0; i < rows; i++) {
sum += matrix[i][j];
}
pq.push(sum);
}
col_scores.resize(max_deletions + 1);
for (int i = 1; i <= max_deletions; i++) {
long long top = pq.top(); pq.pop();
col_scores[i] = col_scores[i-1] + top;
pq.push(top - (long long)rows * penalty);
}
}
long long solve_matrix_problem() {
compute_row_scores();
compute_col_scores();
long long best_score = -1e18;
for (int i = 0; i <= max_deletions; i++) {
long long current_score = row_scores[i] + col_scores[max_deletions - i]
- (long long)i * (max_deletions - i) * penalty;
if (current_score > best_score) {
best_score = current_score;
}
}
return best_score;
}
int main() {
cin >> rows >> cols >> max_deletions >> penalty;
matrix.resize(rows, vector<int>(cols));
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cin >> matrix[i][j];
}
}
cout << solve_matrix_problem() << endl;
return 0;
}
</int></long></long></long></vector></vector></queue></iostream>
Bracket Sequence Optimization
The third problem involves selecting subsequences from multiple bracket sequences to maximize the count of valid balanced sequences. We use dynamic programming with bitmasking to efficiently explore all possible combinations.
For each sequence, we track the prefix sums and minimum prefix sums to determine valid starting points for combining sequences.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX_SEQUENCES = 25;
const int MAX_LENGTH = 4e5 + 5;
int num_sequences;
vector<string> sequences;
vector<int> total_sums, min_sums;
vector<vector>> valid_counts;
int dp[1 << (MAX_SEQUENCES - 5)];
int current_sum[1 << (MAX_SEQUENCES - 5)];
void preprocess_sequences() {
total_sums.resize(num_sequences);
min_sums.resize(num_sequences, 0);
valid_counts.resize(num_sequences, vector<int>(MAX_LENGTH, 0));
for (int i = 0; i < num_sequences; i++) {
int sum = 0;
for (char c : sequences[i]) {
sum += (c == '(') ? 1 : -1;
if (sum < min_sums[i]) {
min_sums[i] = sum;
}
if (min_sums[i] >= sum) {
valid_counts[i][-sum]++;
}
total_sums[i] = sum;
}
}
}
int solve_bracket_problem() {
preprocess_sequences();
int max_score = 0;
fill(dp, dp + (1 << num_sequences), -1e9);
dp[0] = 0;
for (int mask = 0; mask < (1 << num_sequences); mask++) {
for (int i = 0; i < num_sequences; i++) {
if (!(mask & (1 << i))) {
int new_mask = mask | (1 << i);
if (current_sum[mask] + min_sums[i] >= 0) {
if (dp[mask] + valid_counts[i][current_sum[mask]] > dp[new_mask]) {
dp[new_mask] = dp[mask] + valid_counts[i][current_sum[mask]];
current_sum[new_mask] = current_sum[mask] + total_sums[i];
if (dp[new_mask] > max_score) {
max_score = dp[new_mask];
}
}
} else {
int score = dp[mask] + valid_counts[i][current_sum[mask]];
if (score > max_score) {
max_score = score;
}
}
}
}
if (dp[mask] > max_score) {
max_score = dp[mask];
}
}
return max_score;
}
int main() {
cin >> num_sequences;
sequences.resize(num_sequences);
for (int i = 0; i < num_sequences; i++) {
cin >> sequences[i];
}
cout << solve_bracket_problem() << endl;
return 0;
}
</int></vector></int></string></algorithm></vector></iostream>
Path Construction Algorithm
The final problem involves constructing a directed graph where the number of distinct path lengths matches a given target value. The solution involves binary decomposition of the target value and constructing edges accordingly.
For powers of 2, we use a simple chain structure. For general values, we decompose the target into binary components and add edges that cover the required ranges.
#include <iostream>
#include <vector>
using namespace std;
struct Edge {
int from, to, weight;
};
int target_value;
vector<edge> edges;
vector<int> vertices;
int count_log2(int x) {
int result = 0;
while (x) {
result++;
x >>= 1;
}
return result;
}
void construct_base_chain(int log2_val) {
int num_vertices = log2_val + 1;
vertices.resize(num_vertices);
for (int i = 0; i < num_vertices; i++) {
vertices[i] = i + 1;
}
for (int i = 0; i < num_vertices - 1; i++) {
int weight = 1 << (num_vertices - i - 2);
edges.push_back({vertices[i], vertices[i+1], weight});
edges.push_back({vertices[i], vertices[i+1], 0});
}
}
void add_special_edges(int remaining, int current_max, int log2_val) {
for (int p = log2_val; p >= 0; p--) {
if (remaining >= (1 << p)) {
if (log2_val - p == 1) {
edges.push_back({1, vertices[log2_val - 1], target_value});
} else {
edges.push_back({1, vertices[log2_val - p - 1], current_max});
remaining -= (1 << p);
current_max += (1 << p);
}
}
}
}
vector<edge> solve_path_problem(int q) {
edges.clear();
target_value = q;
int log2_val = count_log2(q);
construct_base_chain(log2_val);
int remaining = q - ((1 << (log2_val - 1)) - 1);
int current_max = 1 << (log2_val - 1);
add_special_edges(remaining, current_max, log2_val);
return edges;
}
int main() {
int q;
cin >> q;
vector<edge> result_edges = solve_path_problem(q);
int num_vertices = count_log2(q) + 1;
cout << num_vertices << " " << result_edges.size() << endl;
for (const auto& edge : result_edges) {
cout << edge.from << " " << edge.to << " " << edge.weight << endl;
}
return 0;
}
</edge></edge></int></edge></vector></iostream>