J1001 gcd
Problem solution
KaTeX parse error: Expected 'EOF', got '&' at position 253: ...d(k, t) = 1] &̲ \text{if }t = ...
$\ phi (n) = n * \ prod (1 - \ frac {1} {p_i}) = n * \ prod {\ frac {p_i - 1} {p_i} & [\ text {if} n = \ prod {p_i ^ {a_i}}, p_i \ text {is the quality factor}] \ $
Time complexity: O ( n ) O(n) O(n)
Replenishment tips:
Looking directly at the result, it seems that O ( n ) O(n) O(n), but since the number of divisors of n is very small (for example, the maximum number of divisors in the int range is 1536), the actual speed ratio is O ( n ) O(n) O(n) is much smaller. (at least) 1 0 12 10^{12} 1012 (no problem)
code
#include<bits/stdc++.h> using namespace std; #define int long long vector<int> get_divisors(int n) { vector<int> res; for(int i = 1; i <= n / i; i++) if(n % i == 0) { res.push_back(i); if(i != n / i) res.push_back(n / i); } sort(res.begin(), res.end()); return res; } int phi(int x) { int res = x; for (int i = 2; i <= x / i; i ++ ) if (x % i == 0) { res = res / i * (i - 1); while (x % i == 0) x /= i; } if (x > 1) res = res / x * (x - 1); return res; } signed main() { int n, ans = 0; cin >> n; vector<int> divisors = get_divisors(n); for (int& divisor : divisors) { ans += divisor * phi(n / divisor); } cout << ans << endl; return 0; }
J1002 decomposition quality factor?
Problem solution
Wilson theorem: if p is prime, then ( p − 1 ) ! ≡ − 1 ( m o d p ) (p-1)! \equiv -1(mod \quad p) (p−1)!≡−1(modp).
The inverse proposition of Wilson's theorem is also right: when n is a positive integer and n ≥ 2 n \ge 2 n ≥ 2, if ( n − 1 ) ! ≡ − 1 ( m o d n ) (n-1)! \equiv -1(mod \quad n) (n−1)! ≡− 1(modn), then n is a prime number.
The time complexity of judging prime number by trial division and decomposing prime factor by trial division are the same O ( log n ) O(\log{n}) O(logn)~ O ( n ) O(\sqrt{n}) O(n ).
The complexity of qualitative division and direct division can be achieved O ( T ∗ n ) O(T * \sqrt{n}) O(T∗n ). (this will definitely get stuck. It's impossible to think of a bare board AC)
So you can put less than or equal to 1 0 9 \sqrt{10^9} 109 The prime number is preprocessed, and the prime number is used to judge the prime number and decompose the prime factor. The time complexity is $o (t * \ frac {\ sqrt {n} {\ log {\ sqrt n}}) $.
Less than or equal to 1 0 5 10^5 There are only 9592 prime numbers of 105 , less than or equal to 4 ∗ 1 0 4 4*10^4 The prime number of 4 * 104 is only 4203. Therefore, every time we judge the prime number and decompose the prime factor, we will not exceed 4203 times.
Of course, there are more complex methods of judging prime numbers and decomposing quality factors, but you don't need to fully understand these two methods. Just copy the board during the game. (prime number) O ( k ∗ log 2 n ∗ log log n ∗ log log log n ) O(k * \log ^2 n * \log \log n * \log \log \log n) O(k∗log2n∗loglogn∗logloglogn); Decomposition quality factor O ( n 4 ∗ log n ) O(\sqrt[4]{n} * \log n) O(4n ∗logn))
code
#include<bits/stdc++.h> using namespace std; #define int long long #define x first #define y second const int N = 1e5 + 10, p = 1e9 + 7; int primes[N], cnt; // Primes [] stores all primes bool st[N]; // st[x] is storage x screened out void get_primes(int n) { for(int i = 2; i <= n; i++) { if(!st[i]) primes[cnt ++] = i; for(int j = 0; primes[j] <= n / i; j++) { st[primes[j] * i] = true; //primes[j] is the minimum prime factor of primes[j] * i // When I% P [J] = = 0, P [J] is the minimum prime factor of I (P [J] traverses from small to large), and P [J] must be the minimum prime factor of p[j]*i; When i%p[j]= When 0, P [J] is less than all the prime factors of I, and P [J] must also be the minimum prime factor of p[j]*i if(i % primes[j] == 0) break; //primes[j] must be the minimum prime factor of i to ensure that the composite number will only be screened out by its minimum prime factor and end in advance at the minimum prime factor of i to prevent dead cycle optimization and ensure that it is linear } } } bool isprime(int a) { if (a <= 1) return false; int sq = sqrt(a); for (int i = 0; primes[i] <= sq && i < cnt; i ++) { if(a % primes[i] == 0) return false; } return true; } void solve() { int a; cin >> a; if (isprime(a)) { cout << "Yes" << endl; } else { cout << "No" << endl; } for (int i = 0; primes[i] <= a / primes[i] && i < cnt; i ++) { if(a % primes[i] == 0) { a /= primes[i]; cout << primes[i] << " "; while (a % primes[i] == 0) { a /= primes[i]; } } } if(a > 1) { cout << a; } cout << endl; } signed main() { int t; cin >> t; get_primes(1e5); while(t --) { solve(); } return 0; }
L1001 dry rice
Problem solution
Mixed knapsack template question.
Hybrid backpack can be considered as a mixture of 01 backpack, complete backpack and multiple backpacks. Both multiple backpacks and complete backpacks can be transformed into 01 backpack for solution.
code
#include <iostream> #include<stdlib.h> using namespace std; int n, m, v[100010], w[100010], f[100010]; int main() { cin >> n >> m; int cnt = 1; for (int i = 1; i <= n; i++) { int a, b, s; cin >> a >> b >> s; int k = 1; if (s == 0)s = m / a;//Convert a full knapsack into a multiple knapsack while (k <= s) { v[cnt] = a * k; w[cnt] = b * k; s -= k; k *= 2; cnt++; } if (s > 0) { v[cnt] = s * a; w[cnt] = s * b; cnt++; } }//Binary optimization of multiple knapsacks into 01 knapsack for (int i = 1; i <= cnt; i++) { for (int j = m; j >= v[i]; j--) { f[j] = max(f[j], f[j - v[i]] + w[i]); } }//01 knapsack problem cout << f[m] << endl; return 0; }
L1002 maximum discontinuous sequence sum
Problem solution
Monotone queue optimization dp template
Positive consideration:
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0] indicates the maximum value when the point is not selected
d
p
[
i
]
[
1
]
dp[i][1]
dp[i][1] represents the maximum value when the point is selected
d
p
[
i
]
[
0
]
=
m
a
x
(
d
p
[
i
−
1
]
[
0
]
,
d
p
[
i
−
1
]
[
1
]
)
dp[i][0]=max(dp[i-1][0],dp[i-1][1])
dp[i][0]=max(dp[i−1][0],dp[i−1][1]);
d
p
[
i
]
[
1
]
=
m
a
x
(
d
p
[
i
−
j
]
[
0
]
+
s
u
m
[
i
]
−
s
u
m
[
j
]
)
dp[i][1]=max(dp[i-j][0]+sum[i]-sum[j])
dp[i][1]=max(dp[i−j][0]+sum[i]−sum[j]); (1 = < J < = k-1) / / sum[a] represents the prefix sum, and point J represents the selection from the jth point in front of I to point I continuously. Therefore, the distance between i-j and j should be less than or equal to K, and cycle J
The monotone queue can be used for optimization algorithm, and the transfer equation can be transformed into
d
p
[
i
]
[
1
]
=
m
a
x
(
d
p
[
i
−
j
]
[
0
]
−
s
u
m
[
j
]
)
+
s
u
m
[
i
]
dp[i][1]=max(dp[i-j][0]-sum[j])+sum[i]
dp[i][1]=max(dp[i−j][0]−sum[j])+sum[i]; Monotonic queue can be used for optimization, and the first queue maintenance team is
d
p
[
i
]
[
0
]
−
S
[
i
]
dp[i][0]-S[i]
dp[i][0] − S[i] is the largest monotonic queue, and the queue decreases monotonically
Reverse thinking:
Remove one from every k+1 number to ensure the minimum removal
d
p
[
i
]
=
m
a
x
(
d
p
[
i
−
j
]
+
e
[
i
]
)
dp[i]=max(dp[i-j]+e[i])
dp[i]=max(dp[i−j]+e[i]); (1 = < J < = k-1) dp[x] is the minimum reduction of X
Final thinking
Then start enumerating from the first point
Join the team
If the distance from the leader of the team to this point is greater than k + 1, the leader of the team will pop up
Why k + 1
Because this is an unselected number
The longest continuous interval is the length of k
The unselected number will be on both sides of this interval
In this case, the distance is k + 1
And this is the longest case
So it's greater than k + 1
Then because you have to choose the smallest one
Then put the tail of the team larger than this f[i] and pop it up
Because with a smaller value than the tail of the team, the tail of the team is unlikely to appear
First pop up the value of the queue leader that is out of range
Then process the value of f[i]
At the end of the pop-up line
Because the value of f[i] depends on the minimum value in the previous legal interval
We should first pop up the illegal ones in the interval
Otherwise, we can't guarantee f[i] legality
And the comparison basis of pop-up is the size of f[i]
So first process the value of f[i] before popping the tail of the queue
code
#include<iostream> #include<cstdio> #define ll long long #define linf 99999999999999LL using namespace std; inline int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } int n, K, l, r; ll ans, mn = linf, f[100005];//Used to store the minimum amount subtracted before each point int e[100005]; struct data { int num; ll v; }q[100005];//Monotone priority queue, num is used to store the location, and v is used to store the minimum subtraction int main() { n = read(); K = read(); for (int i = 1; i <= n; i++) e[i] = read(), ans += e[i]; for (int i = 1; i <= n; i++) { f[i] = e[i] + q[l].v; while (q[r].v > f[i] && l <= r)r--;//When the contribution of the rightmost end of the current queue is greater than the minimum amount of the current point, it is proved that the contribution of this point will not contribute in subsequent points q[++r].v = f[i]; q[r].num = i; while (q[l].num < i - K)l++;//Update the value of l to ensure that the distance between l and the current point does not exceed k } for (int i = n - K; i <= n; i++) mn = min(mn, f[i]); printf("%lld", ans - mn); return 0; }
L10001 good string
Problem solution
Check in question. Just judge whether the string contains each character of "haust".
code
#pragma GCC optimize(2) #include <iostream> using namespace std; const int maxn = 1e4 + 10; int main() { ios::sync_with_stdio(0); cin.tie(0); int _t; cin >> _t; while (_t--) { string s; cin >> s; if (s.find('h') != -1 and s.find('a') != -1 and s.find('u') != -1 and s.find('s') != -1 and s.find('t') != -1) { cout << "YES" << '\n'; } else { cout << "NO" << '\n'; } } return 0; }
L10002 course selection table
Problem solution
A contradictory situation is
The prerequisites for course 1 are course 2
The prerequisite for course 2 is course 1
or
The prerequisites for course 1 are course 1
or
Prerequisite for course 1 prerequisite for course... Prerequisite for course 1
Namely:
Regard the course as a node and the prerequisite relationship as a directed edge
The prerequisites for course 1 are course 2
The relationship is: 2 ----- > 1
Therefore, it is only necessary to judge whether there is a ring in the figure.
Next, use topological sorting to judge the ring.
code
/* hello world! Just do it! start time:2022-02-25 12:48:13.096291 */ // #pragma GCC optimize (2) // #pragma G++ optimize (2) #include <bits/stdc++.h> #define zero(x) memset(x, 0, sizeof(x)); #define one(x) memset(x, -1, sizeof(x)); #define m_INF(x) memset(x, 0x3f, sizeof(x)); #define m_inf(x) memset(x, 0x3f, sizeof(x)); #define m_f_INF(x) memset(x, -0x3f, sizeof(x)); #define m_f_inf(x) memset(x, -0x3f, sizeof(x)); #define all(x) x.begin(), x.end() #define endl "\n" #define fi first #define se second #define lbt(x) ((x) & (-x)) struct cmpl { template <typename A, typename B> bool operator()(const A &a1, const B &b1) { return b1 < a1; } }; struct cmpg { template <typename A, typename B> bool operator()(const A &a1, const B &b1) { return a1 < b1; } }; #define p_ql(x) priority_queue<x, vector<x>, cmpl> #define p_qlp(x, y) priority_queue<pair<x, y>, vector<pair<x, y>>, cmpl> #define p_qg(x) priority_queue<x, vector<x>, cmpg> #define p_qgp(x, y) priority_queue<pair<x, y>, vector<pair<x, y>>, cmpg> template <class T> bool ckmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; } template <class T> bool ckmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; } #define fo(i, from, to) for (int i = (from), ooo = (from) < (to) ? 1 : -1, oooo = (to) + ooo; i != oooo; i += ooo) #define fol(i, from, to) \ for (long long i = (from), ooo = (from) < (to) ? 1 : -1, oooo = (to) + ooo; i != oooo; i += ooo) #define foo(i, ooo) for (auto i = ooo.rbegin(); i != ooo.rend(); ++i) #define foa(i, from, to) for (int i = (from), ooo = (to); i <= ooo; ++i) #define fos(i, from, to) for (int i = (from), ooo = (to); i >= ooo; --i) using namespace std; #ifndef LOCAL # define dbg(...) ; #endif #define itn int //#define int long long typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int inf = 0x3f3f3f3f, dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1}, INF = 0x3f3f3f3f, f_inf = -1044266559, f_INF = -1044266559; const int maxn = 1e6 + 10; const int N = 16; int n, m; void init() { } int tot, h[maxn], nxt[maxn], e[maxn]; void add(int x, int y) // Adjacency table storage map { e[++tot] = y, nxt[tot] = h[x], h[x] = tot; } int inv[maxn]; void solve() { cin >> n >> m; int x, y; foa(i, 1, m) { cin >> x >> y; add(y, x); // Convert relationship to directed edge inv[x]++; // x point penetration plus 1 } queue<int> q; foa(i, 1, n) if (!inv[i]) q.push(i); // Click in queue with penetration of 0 int num = 0; while (q.size()) { auto t = q.front(); q.pop(); num++; // What can be learned in this course for (int i = h[t]; i; i = nxt[i]) { if (--inv[e[i]] == 0) q.push(e[i]); // After removing this point, reduce the penetration of the connected points } } if (num == n) cout << "Yes\n"; // The courses you can learn are num else cout << "No\n"; } signed main() { #ifdef LOCAL // freopen("read.in", "r", stdin); // freopen("write.out", "w", stdout); #endif std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); init(); int t = 0, num2 = 0; t = 1; if (!t) cin >> t; while (t--) { // cout<<"Case "<<++num2<<": "; solve(); } return 0; int num1 = 0; // while (scanf("%d", &n) !=-1 && n) while (cin >> n && n) { // cout<<"Case "<<++num1<<": "; solve(); } return 0; }
P10086 play with numbers
Problem solution
Simple simulation, using STL to reduce the amount of code.
code
/* hello world! Just do it! start time:2022-02-16 13:52:35.424691 */ // #pragma GCC optimize (2) // #pragma G++ optimize (2) #include <bits/stdc++.h> #define zero(x) memset(x, 0, sizeof(x)); #define one(x) memset(x, -1, sizeof(x)); #define m_INF(x) memset(x, 0x3f, sizeof(x)); #define m_inf(x) memset(x, 0x3f, sizeof(x)); #define m_f_INF(x) memset(x, -0x3f, sizeof(x)); #define m_f_inf(x) memset(x, -0x3f, sizeof(x)); #define all(x) x.begin(), x.end() #define endl "\n" #define fi first #define se second #define lbt(x) ((x) & (-x)) struct cmpl { template <typename A, typename B> bool operator()(const A &a1, const B &b1) { return b1 < a1; } }; struct cmpg { template <typename A, typename B> bool operator()(const A &a1, const B &b1) { return a1 < b1; } }; #define p_ql(x) priority_queue<x, vector<x>, cmpl> #define p_qlp(x, y) priority_queue<pair<x, y>, vector<pair<x, y>>, cmpl> #define p_qg(x) priority_queue<x, vector<x>, cmpg> #define p_qgp(x, y) priority_queue<pair<x, y>, vector<pair<x, y>>, cmpg> template <class T> bool ckmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; } template <class T> bool ckmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; } #define fo(i, from, to) for (int i = (from), ooo = (from) < (to) ? 1 : -1, oooo = (to) + ooo; i != oooo; i += ooo) #define fol(i, from, to) \ for (long long i = (from), ooo = (from) < (to) ? 1 : -1, oooo = (to) + ooo; i != oooo; i += ooo) #define foo(i, ooo) for (auto i = ooo.rbegin(); i != ooo.rend(); ++i) #define foa(i, from, to) for (int i = (from), ooo = (to); i <= ooo; ++i) #define fos(i, from, to) for (int i = (from), ooo = (to); i >= ooo; --i) using namespace std; #ifndef LOCAL # define dbg(...) ; #endif #define itn int #define int long long typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int inf = 0x3f3f3f3f, dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1}, INF = 0x3f3f3f3f, f_inf = -1044266559, f_INF = -1044266559; const int maxn = 1e6 + 10; const int N = 16; int n, m; void init() { } int getv(string s, int v) { if (v) sort(all(s), greater<char>()); // Sort from large to small else sort(all(s)); // Sort from small to large int res = 0; for (auto &x : s) res = res * 10 + x - '0'; // Convert a string to a number return res; } int a[maxn]; // Record the value for each location void solve() { cin >> a[1] >> m; map<int, int> mp; // The value of each key is a[i], and the value is I int k = 1e6; foa(i, 2, k) { string s = to_string(a[i - 1]); // Convert int to string int n = getv(s, 1) - getv(s, 0); // Maximum minus minimum simulation a[i] = n; if (mp.count(n)) { // Loop in array int p = mp[n], len = i - p; if (m >= i) m = p + (m - p) % len; // The calculation is in the position of the loop section cout << a[m] << endl; return; } mp[n] = i; } cout << "-1\n"; //There is no cycle } signed main() { #ifdef LOCAL freopen("read.in", "r", stdin); freopen("write.out", "w", stdout); #endif std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); init(); int t = 0, num2 = 0; if (!t) cin >> t; while (t--) { // cout<<"Case "<<++num2<<": "; solve(); } return 0; int num1 = 0; // while (scanf("%d", &n) !=-1 && n) while (cin >> n) { // cout<<"Case "<<++num1<<": "; solve(); } return 0; }
P1008611 small water play paper
Problem solution
In the previous operation simulation, each piece of paper is assigned an id. each operation records the upper left corner and upper right corner of a piece of paper, and then uses the array top [] to additionally record the priority of this piece of paper. Each operation will maximize the priority of the currently operated piece of paper.
Priority satisfaction: the paper with high priority must be on the paper with low priority.
After the operation, discretize the coordinates of each piece of paper.
Open a two-dimensional array table [] [] to simulate the desktop, draw each piece of paper on the desktop, and the paper with high priority can cover the paper with low priority.
Just count the id of how many pieces of paper there are.
code
/* hello world! Just do it! start time:2022-02-16 19:23:18.266489 */ // #pragma GCC optimize (2) // #pragma G++ optimize (2) #include <bits/stdc++.h> #define zero(x) memset(x, 0, sizeof(x)); #define one(x) memset(x, -1, sizeof(x)); #define m_INF(x) memset(x, 0x3f, sizeof(x)); #define m_inf(x) memset(x, 0x3f, sizeof(x)); #define m_f_INF(x) memset(x, -0x3f, sizeof(x)); #define m_f_inf(x) memset(x, -0x3f, sizeof(x)); #define all(x) x.begin(), x.end() #define endl "\n" #define fi first #define se second #define lbt(x) ((x) & (-x)) struct cmpl { template <typename A, typename B> bool operator()(const A &a1, const B &b1) { return b1 < a1; } }; struct cmpg { template <typename A, typename B> bool operator()(const A &a1, const B &b1) { return a1 < b1; } }; #define p_ql(x) priority_queue<x, vector<x>, cmpl> #define p_qlp(x, y) priority_queue<pair<x, y>, vector<pair<x, y>>, cmpl> #define p_qg(x) priority_queue<x, vector<x>, cmpg> #define p_qgp(x, y) priority_queue<pair<x, y>, vector<pair<x, y>>, cmpg> template <class T> bool ckmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; } template <class T> bool ckmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; } #define fo(i, from, to) for (int i = (from), ooo = (from) < (to) ? 1 : -1, oooo = (to) + ooo; i != oooo; i += ooo) #define fol(i, from, to) \ for (long long i = (from), ooo = (from) < (to) ? 1 : -1, oooo = (to) + ooo; i != oooo; i += ooo) #define foo(i, ooo) for (auto i = ooo.rbegin(); i != ooo.rend(); ++i) #define foa(i, from, to) for (int i = (from), ooo = (to); i <= ooo; ++i) #define fos(i, from, to) for (int i = (from), ooo = (to); i >= ooo; --i) using namespace std; #ifndef LOCAL # define dbg(...) ; #endif #define itn int //#define int long long typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int inf = 0x3f3f3f3f, dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1}, INF = 0x3f3f3f3f, f_inf = -1044266559, f_INF = -1044266559; const int maxn = 4e2 + 10; const int N = 16; int n, m; void init() { } struct node { int x1, y1, x2, y2; } cur[maxn]; // The location of the paper with id I is stored in cur[i] itn top[maxn], opend; // Number of priority pieces int find(int x, int y) // Find the top piece of paper in position (x,y) { int res = -1; foa(i, 1, opend) { if ((cur[i].x1 <= x && x <= cur[i].x2 && cur[i].y1 <= y && y <= cur[i].y2) && (res == -1 || top[i] > top[res])) res = i; } return res; } int val[maxn][maxn]; // Array simulation table vector<itn> vt; // Discretization operation int id(int x) // Discretization operation { return lower_bound(all(vt), x) - vt.begin(); } void solve() { cin >> n; itn x1, y1, x2, y2; char s; foa(i, 1, n) { cin >> s >> x1 >> y1; if (s == 'Q') { cin >> x2 >> y2; cur[++opend] = {x1, y1, x2, y2}; // Add pieces of paper top[opend] = i; // Each operation changes the priority of the operation paper to the highest } else { int v = find(x1, y1); // Find the top piece of paper // dbg(i,v,cur[1].x1) if (v != -1) top[v] = i; // Each operation changes the priority of the operation paper to the highest if (s == 'W') { // translation cin >> x2 >> y2; if (v == -1) continue; // If there is no paper in this position, continue this operation after reading the data cur[v].x1 += x2, cur[v].x2 += x2; cur[v].y1 += y2, cur[v].y2 += y2; } else if (s == 'R') { // When deleting, I changed the coordinates to inf instead of deleting. Remember to make a special judgment when processing in the future if (v == -1) continue; // If there is no paper in this position, continue cur[v] = {inf, inf, inf, inf}; } } } // int res=-1; // foa(i,1,opend)if(cur[i].x1!=inf&&(res==-1||top[i]>top[res]))res=i; // if(res==-1)cout<<"Nothing\n"; // else cout<<cur[res].x1<<" "<<cur[res].y1<<" "<<cur[res].x2<<" "<<cur[res].y2<<endl; // dbg(res,top,cur[1].x1) foa(i, 1, opend) { // Discretization operation vt.push_back(cur[i].x1); vt.push_back(cur[i].x2); vt.push_back(cur[i].y1); vt.push_back(cur[i].y2); } sort(all(vt)); vt.erase(unique(all(vt)), vt.end()); foa(i, 1, opend) { auto &t = cur[i]; if (t.x1 == inf) continue; foa(j, id(t.x1), id(t.x2)) foa(k, id(t.y1), id(t.y2)) { auto &h = val[j][k]; if (h == 0 || top[i] > top[h]) h = i; // There is no paper in this position, or higher priority is placed in this position } } set<int> st; foa(i, 0, vt.size()) foa(j, 0, vt.size()) if (val[i][j]) st.insert(val[i][j]); // set statistics cout << st.size() << endl; // dbg(val,vt,opend) } signed main() { #ifdef LOCAL freopen("read.in", "r", stdin); freopen("write.out", "w", stdout); #endif std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); init(); int t = 0, num2 = 0; t = 1; if (!t) cin >> t; while (t--) { // cout<<"Case "<<++num2<<": "; solve(); } return 0; int num1 = 0; // while (scanf("%d", &n) !=-1 && n) while (cin >> n && n) { // cout<<"Case "<<++num1<<": "; solve(); } return 0; }
P888 Xiaoshui has a water problem
Problem solution
Adapted from CF769 div2 D
https://codeforces.com/contest/1632/problem/D
See the official explanation.
Here is an O(n log a log a) approach
Scan the array before and after forgetting, modify the i-th position, and only consider making the first I numbers meet the conditions of the topic.
When modifying, you can modify the number to a prime number greater than the length of the array. In this way, after modification, the first i - 1 numbers must meet the conditions without affecting the following numbers.
Assuming the i-th number is currently scanned,
It is easy to know that looking forward from i, the continuous maximum common divisor does not increase in turn.
That is: $GCD (a_i) > = GCD (a_ {I - 1}, a_i) > = GCD (a_ {I - 2}, a_ {I - 1}, a_i)... $its value does not increase.
Therefore, a structure can be used to store the representation of {l,r,v} j ∈ [ l , r ] j \in [l, r] The value of gcd of j ∈ [l,r] satisfying all numbers from j to i is v.
Therefore, you only need to check whether there is interval satisfaction i − r g c d ( a i , v ) + 1 < = g c d ( a i , v ) < = i − l g c d ( a i , v ) + 1 i - r_{gcd(a_i, v)} + 1 <= gcd(a_i, v) <= i-l_{gcd(a_i, v)} + 1 i − rgcd(ai, v) + 1 < = GCD (AI, v) < = i − lgcd(ai, v) + 1 is equivalent to l g c d ( a i , v ) < = i − g c d ( a i , v ) + 1 < = r g c d ( a i , v ) l_{gcd(a_i, v)}<= i-gcd(a_i, v)+1 <=r_{gcd(a_i, v)} lgcd(ai, v) < = I − gcd(ai, v) + 1 < = rgcd (AI, v), that is, there is a gcd whose interval length is equal to the interval
If this condition is met, modify it a i a_i ai , this value is sufficient.
Then maintain the value of this structure when i moves to the next bit.
The correctness and time complexity of the algorithm should be carefully considered and proved by the reader.
code
/* hello world! Just do it! start time:2022-02-06 12:29:48.109593 */ // #pragma GCC optimize (2) // #pragma G++ optimize (2) #include <bits/stdc++.h> #define zero(x) memset(x, 0, sizeof(x)); #define one(x) memset(x, -1, sizeof(x)); #define m_INF(x) memset(x, 0x3f, sizeof(x)); #define m_inf(x) memset(x, 0x3f, sizeof(x)); #define m_f_INF(x) memset(x, -0x3f, sizeof(x)); #define m_f_inf(x) memset(x, -0x3f, sizeof(x)); #define all(x) x.begin(), x.end() #define endl "\n" #define fi first #define se second #define lbt(x) ((x) & (-x)) struct cmpl { template <typename A, typename B> bool operator()(const A &a1, const B &b1) { return b1 < a1; } }; struct cmpg { template <typename A, typename B> bool operator()(const A &a1, const B &b1) { return a1 < b1; } }; #define p_ql(x) priority_queue<x, vector<x>, cmpl> #define p_qlp(x, y) priority_queue<pair<x, y>, vector<pair<x, y>>, cmpl> #define p_qg(x) priority_queue<x, vector<x>, cmpg> #define p_qgp(x, y) priority_queue<pair<x, y>, vector<pair<x, y>>, cmpg> template <class T> bool ckmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; } template <class T> bool ckmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; } #define fo(i, from, to) for (int i = (from), ooo = (from) < (to) ? 1 : -1, oooo = (to) + ooo; i != oooo; i += ooo) #define fol(i, from, to) \ for (long long i = (from), ooo = (from) < (to) ? 1 : -1, oooo = (to) + ooo; i != oooo; i += ooo) #define foo(i, ooo) for (auto i = ooo.rbegin(); i != ooo.rend(); ++i) #define foa(i, from, to) for (int i = (from), ooo = (to); i <= ooo; ++i) #define fos(i, from, to) for (int i = (from), ooo = (to); i >= ooo; --i) using namespace std; #ifndef LOCAL # define dbg(...) #endif #define itn int //#define int long long typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int inf = 0x3f3f3f3f, dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1}, INF = 0x3f3f3f3f, f_inf = -1044266559, f_INF = -1044266559; const int maxn = 2e5 + 10; const int N = 16; int n, m; void init() { } // gcd l r map<int, pii> mp; // I use map and pair instead of structure, and the maximum number of data in map is log(max(a[i]) int a[maxn], ans[maxn]; void solve() { cin >> n; foa(i, 1, n) cin >> a[i]; foa(i, 1, n) { ans[i] = ans[i - 1]; if (a[i] == 1) { // 1. It doesn't have to be satisfied. It needs special treatment ans[i]++; // cout<<ans[i]<<" "; mp.clear(); continue; } int flag = 1; // dbg(i,a[i],mp) for (auto it = mp.begin(); it != mp.end();) { auto x = *it; // if(x.se.se==i-1)x.se.se=i; int t = __gcd(x.fi, a[i]); if (mp.count(t)) mp[t].se = x.se.se; //Update map data else mp[t] = x.se; int l = i - t + 1; if (l >= mp[t].fi && l <= mp[t].se) { // There are conditions that are not met ans[i]++; mp.clear(); flag = 0; break; } it++; if (t != x.fi) mp.erase(x.fi); // Delete obsolete data maintenance map } if (flag && !mp.count(a[i])) mp[a[i]] = {i, i}; // Special judgment if (flag) mp[a[i]].se = i; // Special judgment // cout<<ans[i]<<" "; } cout << ans[n] << endl; } signed main() { #ifdef LOCAL // freopen("read.in", "r", stdin); // freopen("write.out", "w", stdout); #endif std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); init(); int t = 0, num2 = 0; t = 1; if (!t) cin >> t; while (t--) { // cout<<"Case "<<++num2<<": "; solve(); } return 0; int num1 = 0; // while (scanf("%d", &n) !=-1 && n) while (cin >> n && n) { // cout<<"Case "<<++num1<<": "; solve(); } return 0; }
T1002 eagle catches chicken
Problem solution
This question examines mathematical ability or programming ability.
The mathematical method is: first calculate the distance between the eagle and the chicken, discuss the time period when the chicken flees from the eagle and the time period when the chicken approaches the eagle according to the situation, and sum it.
The programming method is: directly draw the time required for the eagle to reach each grid, and then simulate the movement of the chicken. If the eagle can reach the specified position at the time point after the chicken moves, it is judged that it can be caught.
code
#include <iostream> #include <cstring> #include <cmath> #define maxn 1010 using namespace std; int n,vis[maxn][maxn]; void ly_dfs(int x,int y) // Circle around the center { vis[x][y]=1; for (int i=1;i<2*n;i++) { for (int j=0;j<i;j++) // Starting from four vertices, draw i points at a time. { int a=j,b=i-j; if (x+a<=n && y+b<=n) vis[x+a][y+b]=i/2+i%2; if (x-a>=1 && y-b>=1) vis[x-a][y-b]=i/2+i%2; if (x+b<=n && y-a>=1) vis[x+b][y-a]=i/2+i%2; if (x-b>=1 && y+a<=n) vis[x-b][y+a]=i/2+i%2; } } } int main() { cin >> n; int x,y; memset(vis,-1,sizeof(vis)); cin >> x >> y; ly_dfs(x,y); int a,b,c,d; cin >> a >> b >> c >> d; if (b!=d) { x=(d-b)/abs(d-b); int cnt=1; /* for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) { cout << vis[i][j] <<" "; } cout << endl; }*/ for (int i=b+x;i!=d;i+=x) // The chicken was caught walking { if (vis[a][i]<=cnt) { cout << vis[a][i] << endl; return 0; } cnt++; } } cout << vis[a][d] << endl; // The chicken finally stopped where it was return 0; }
T1003 mining
Problem solution
The knowledge point investigated in this problem is the minimum spanning tree. After knowing this knowledge point, you only need to think a little to obtain the solution.
Each mine can be regarded as a point, and the value of excavation difficulty * distance between mines is an edge.
This is to find n-1 edges on a graph with full edges to make the graph connected.
code
#include <bits/stdc++.h> #define maxn 1010 using namespace std; struct pii { int x,y,value; bool operator < (pii temp) const { return value < temp.value; } }arr[maxn]; int n,m,vis[maxn][maxn],fa[maxn]; pii krr[maxn*maxn]; int dis(int i,int j) { return abs(arr[i].x-arr[j].x)+abs(arr[i].y-arr[j].y); } int find(int x) { if (fa[x]==x) return x; else return fa[x]=find(fa[x]); } int main() { cin >> n >> m; memset(vis,0,sizeof(vis)); for (int i=1;i<=n;i++) { int x,y; cin >> x >> y; arr[i]=(pii){x,y,0}; } for (int i=0;i<m;i++) { int x,y,z; cin >> x >> y >> z; if (x>y) swap(x,y); vis[x][y]+=z; } int tot=0; for (int i=1;i<=n;i++) { for (int j=1;j<=i;j++) { krr[tot++]=(pii){j,i,dis(i,j)*(vis[j][i]+1)}; } } sort(krr,krr+tot); long long ans=0; for (int i=1;i<=n;i++) fa[i]=i; // cout << "||||" << endl; for (int i=0;i<tot;i++) { int a=krr[i].x,b=krr[i].y,c=krr[i].value; // cout << a << " " << b << " " <<c << endl; if (find(a)!=find(b)) { fa[find(a)]=find(b); ans+=c; // for (int k=1;k<=n;k++) // cout <<fa[k] << " "; // cout << endl; } } cout << ans << endl; return 0; }
X1001 make up lessons
Problem solution
This question tests the treatment of space
Due to the large amount of data, if you use array storage and reordering, it will explode space
We notice that the data except the maximum k number and the minimum k number only need to be added, and there is no need to do other processing
And the value of k is less than n \sqrt{n} n , that is, 2*k is about 6000, which is far less than 1 0 7 10^7 107. At this time, we have more than enough data space to process
For finding the maximum or minimum k values, an excellent data structure is the priority queue (or heap)
We use small root heap and large root heap to maintain data respectively. When the amount of data in a heap is greater than k, we delete the top of the heap, and finally we can get the maximum K number and the minimum K number respectively
Since the smallest value will be deleted when the amount of data in the small root heap is greater than k, it can always be ensured that the value in the small root heap is the largest K at present when operating on the small root heap
The same is true for big piles
Because we need to process the data in the other stack in the opposite order, we can process the data in the other stack
Finally, the final answer can be obtained by processing the data according to the meaning of the question
(note that the maximum score range is 1 0 18 10^{18} 1018, so it is necessary to turn on long
code
#include<bits/stdc++.h> using namespace std; #define int long long const int MOD=170001; inline long long read(){ long long x=0,y=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x*y; } signed main() { int T=read(); while (T--) { int n=read(), k=read(); priority_queue<int, vector<int>, less<int>> maxRootHeap; priority_queue<int, vector<int>, greater<int>> minRootHeap; int sum = 0; for (int i = 0; i < n; ++i) { int a=read(); sum = (sum+a)%MOD; maxRootHeap.push(a); if (maxRootHeap.size() > k) maxRootHeap.pop(); minRootHeap.push(a); if (minRootHeap.size() > k) minRootHeap.pop(); } stack<int>s; while(minRootHeap.size()){ s.push(minRootHeap.top()); minRootHeap.pop(); } while(s.size()){ sum=(sum+(maxRootHeap.top()+s.top())/2-maxRootHeap.top())%MOD; s.pop(); maxRootHeap.pop(); } cout<<sum<<endl; } }
X1002 make up 2.0
Problem solution
This topic focuses on interval maintenance, which only includes interval modification
It is basically a template question of interval data structures such as line segment tree and tree array
Those who do not know the line segment tree can go to the following website to learn:
https://scefuvh.github.io/segment-tree
Because it is an interval modification, lazyTag needs to be used, otherwise there is a high probability of timeout
Because this problem only outputs the final result, the difference can also AC, and the time complexity is better than the line segment tree.
code
#include<bits/stdc++.h> #define int long long using namespace std; const int N = 1e6 + 10, MOD = 114514; int arr[N]; struct Node { int l, r, w, lazy; #define l(i) node[i].l #define r(i) node[i].r #define w(i) node[i].w #define lazy(i) node[i].lazy #define lc i<<1 #define rc i<<1|1 } node[N << 2]; void update(int i) { w(i) = (w(lc) + w(rc)) % MOD; } void build(int l, int r, int i) { lazy(i) = 1, l(i) = l, r(i) = r; if (l == r) { w(i) = arr[l]; return; } int mid = l + r >> 1; build(l, mid, lc), build(mid + 1, r, rc); update(i); } void pushDown(int i) { w(lc) = w(lc) * lazy(i) % MOD; w(rc) = w(rc) * lazy(i) % MOD; lazy(lc) = lazy(lc) * lazy(i) % MOD; lazy(rc) = lazy(rc) * lazy(i) % MOD; lazy(i) = 1; } void modify(int l, int r, int i) { if (r < l(i) or r(i) < l) return; if (l <= l(i) and r(i) <= r) { w(i) =w(i)* 2%MOD; lazy(i) =lazy(i)* 2%MOD; return; } pushDown(i); modify(l, r, lc), modify(l, r, rc); update(i); } signed main() { int T; cin >> T; while (T--) { int n, q; cin >> n >> q; for (int i = 1; i <= n; ++i) cin >> arr[i]; build(1, n, 1); while (q--) { int t, k; cin >> t >> k; if (t + k - 1 > n) { modify(t, n, 1); modify(1, k - n + t - 1, 1); } else { modify(t, t + k - 1, 1); } } cout << w(1) << endl; } }