2022 Niuke winter vacation algorithm basic training camp 4
A-R
Title Description:
Xiao Hong gets a string of length n, which is only composed of uppercase letters.
Xiao Hong likes red very much (indicated by the letter 'R'), but she hates purple very much (indicated by the letter 'P').
She wants to take a continuous substring that contains at least k 'R' characters and cannot contain 'P' characters.
Can you tell her how many legal schemes can be obtained?
Idea:
Enumerate the left endpoint l and determine the minimum and maximum value of r through two limiting conditions. The method is to preprocess with two prefixes and sums, and then use bisection to find the boundary. After difference, the number of substrings with l as the left endpoint can be obtained, and then accumulated
It looks very simple, but there are some details to pay attention to
- When finding the minimum value of r, it is rr[i - 1]+k that should be dichotomized, not rr[i]+k
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define inf 0x3f3f3f3f #define mod 998244353 #define m_p(a,b) make_pair(a, b) #define mem(a,b) memset((a),(b),sizeof(a)) #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) typedef long long ll; typedef pair <int,int> pii; #define MAX 300000 + 50 int n, m, k; int pr[MAX]; int rr[MAX]; char tr[MAX]; void work(){ cin >> n >> k; for(int i = 1; i <= n; ++i){ cin >> tr[i]; if(tr[i] == 'P')pr[i]++; if(tr[i] == 'R')rr[i]++; pr[i] += pr[i - 1]; rr[i] += rr[i - 1]; } ll ans = 0; for(int i = 1; i <= n; ++i){ if(tr[i] == 'P')continue; ll l = lower_bound(rr + i, rr + n + 1, rr[i - 1] + k) - rr; ll r = lower_bound(pr + i, pr + n + 1, pr[i] + 1) - pr; ans += max(0ll, r - l); } cout << ans << endl; } int main(){ io; work(); return 0; }
B-ary
Title Description:
A string of length n, consisting of only 0-9 characters, q queries, including two operations
- 1 x y means to change the character of bit x to y
- 2 x y outputs the minimum value of a binary that can be represented by bits x to y. this binary must be binary to decimal, and must be legal. Take the modulus of 1e9+7
Idea:
Now let's talk about a very simple point: splice 1234 and 5678 to get 12345678. In fact, this number is 1234 ∗ 1 0 4 + 5678 1234 * 10^4 + 5678 1234 * 104 + 5678, 1 0 4 10^4 104 is because the following number has 4 digits
This is the most important idea of this question
Besides the minimum value, we only need to find the largest number + 1 in [l, r] and calculate it as a base number. One pit is that if the largest number is 0, the base should be set to binary, because the base required by the topic must be 2 to 10 base
Therefore, we can use the segment tree to maintain a maximum value, and then maintain a val value for each binary from 2 to 10
Maintaining the maximum value is very simple, just a pure board
When calculating val, there are roughly three kinds
-
Mid > = t, at this time [s, t] is all on the left subtree, so it is equal to v a l Left son tree val_ {left subtree} val left subtree
-
Mid < s at this time [s, t] is all in the right subtree, so it is equal to v a l right son tree val_ {right subtree} val right subtree, you may wonder why there is no equal sign here. In fact, it is because the interval of the right subtree is [mid + 1, r], that is, mid + 1 < = s, and moving backward is mid < s
-
Mid > = S & & mid < T, at this time v a l Left son tree ∗ enter system right son tree large Small + v a l right son tree val_ {left subtree} * {base} ^ {right subtree size} + val_ {right subtree} val left subtree * base right subtree size + val right subtree. Here, there are two cases according to the size of the right subtree
- R < = t, that is, the right bound that can be processed by the current interval is r, but the target right bound is t, R is on the left of T, and the right bound of the right subtree here is r
- R > t, R is on the right of T, we only need to get the value of T, so the right boundary size of the right subtree is t
To sum up, if the right bound of the right subtree is min(t, r), then the size of the right subtree is mid(t, r) - (mid + 1) + 1, that is, mid(t, r) - mid
Therefore, the general idea is to build a tree and maintain a maxn and a val. for operation 1, we update the values of the two. For operation 2, we first query the maximum value, and ma = maximum value + 1. If ma == 1, then + + ma, and then use ma as base to calculate val
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define inf 0x3f3f3f3f #define mod 1000000007 #define m_p(a,b) make_pair(a, b) #define mem(a,b) memset((a),(b),sizeof(a)) #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) #define ls p<<1 #define rs p<<1|1 typedef long long ll; #define MAX 400000 + 50 int n, m; int op, l, r; char tr[MAX]; int maxn[MAX]; ll val[MAX][12]; ll q_pow(ll a, ll b){ ll ans = 1; while (b) { if(b & 1)ans = ans * a % mod; b >>= 1; a = a * a % mod; } return ans; } inline void pushup(int p, ll len){ maxn[p] = max(maxn[ls], maxn[rs]); for(ll c = 2; c <= 10; ++c)val[p][c] = ((val[ls][c] * q_pow(c, len)) % mod + val[rs][c]) % mod; } inline void built(int p, int l, int r){ if(l == r){ maxn[p] = tr[l] - '0'; for(int c = 2; c <= 10; ++c)val[p][c] = tr[l] - '0'; return; } int mid = (l + r) / 2; built(ls, l, mid); built(rs, mid + 1, r); pushup(p, r - mid); } inline void update(int p, int l, int r, int id, int x){ if(l == r && l == id){ maxn[p] = x; for(int c = 2; c <= 10; ++c)val[p][c] = x; return; } int mid = (l + r) / 2; if(mid >= id)update(ls, l, mid, id, x); else update(rs, mid + 1, r, id, x); pushup(p, r - mid); } inline int getmaxn(int p, int l, int r, int s, int t){ if(l >= s && t >= r){ return maxn[p]; } int mid = (l + r) / 2; int ma = 0; if(mid >= s)ma = max(ma, getmaxn(ls, l, mid, s, t)); if(mid < t)ma = max(ma, getmaxn(rs, mid + 1, r, s, t)); return ma; } inline ll getans(int p, int l, int r, int s, int t, int c){ if(l >= s && t >= r){ return val[p][c]; } int mid = (l + r) / 2; if(mid >= t)return getans(ls, l, mid, s, t, c); else if(mid < s)return getans(rs, mid + 1, r, s, t, c); else{ ll len = min(r, t) - mid; return ((getans(ls, l, mid, s, t, c) * q_pow(c, len)) % mod + getans(rs, mid + 1, r, s, t, c)) % mod; } } void work(){ cin >> n >> m; for(int i = 1; i <= n; ++i)cin >> tr[i]; built(1, 1, n); while (m--) { cin >> op >> l >> r; if(op == 1){ update(1, 1, n, l, r); } else { int c = getmaxn(1, 1, n, l, r) + 1; if(c == 1)++c; cout << getans(1, 1, n, l, r, c) << endl; } } } int main(){ work(); return 0; }
C-blue comet
Title Description:
There are n comets, each of which can shine for t seconds
Enter a string with only B and R, s[i]='B' indicates that the ith is blue comet, s[i] = 'R' indicates that the ith is red comet. Ask how many seconds you can only see blue comet but not red comet
Idea:
Differential prefix sum
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define inf 0x3f3f3f3f #define mod 998244353 #define m_p(a,b) make_pair(a, b) #define mem(a,b) memset((a),(b),sizeof(a)) #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) typedef long long ll; typedef pair <int,int> pii; #define MAX 300000 + 50 int n, m, x; int br[MAX]; int rr[MAX]; char tr[MAX]; void work(){ cin >> n >> m; for(int i = 1; i <= n; ++i)cin >> tr[i]; for(int i = 1; i <= n; ++i){ cin >> x; if(tr[i] == 'B'){ ++br[x]; --br[x + m]; } else{ ++rr[x]; --rr[x + m]; } } for(int x = 1; x <= 200050; ++x){ br[x] += br[x - 1]; rr[x] += rr[x - 1]; } int ans = 0; for(int i = 1; i <= 200050; ++i){ if(br[i] && !rr[i])++ans; } cout << ans << endl; } int main(){ io; work(); return 0; }
D-snow glow
Title Description:
Idea:
Find the minimum value from point to line segment
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define inf 0x3f3f3f3f #define mod 998244353 #define m_p(a,b) make_pair(a, b) #define mem(a,b) memset((a),(b),sizeof(a)) #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) #define y0 y114514 #define eps 1e-7 typedef long long ll; typedef pair <int,int> pii; #define MAX 300000 + 50 int n, m; double x0, y0, x, y; double xx, yy; struct Point{ double x, y; }; float pointToLine(Point s, Point e, Point p) { float ux = e.x - s.x; float uy = e.y - s.y; float vx = p.x - s.x; float vy = p.y - s.y; float wx = p.x - e.x; float wy = p.y - e.y; float umv = ux * vx + uy * vy; float umw = ux * wx + uy * wy; if (umv * umw > 0) { // The perpendicular foot of the point is not on the line segment if (umv > 0) { // The foot is perpendicular to the end side return sqrt(wx * wx + wy * wy); } else { // The vertical foot is on the side of the starting point return sqrt(vx * vx + vy * vy); } } else { // The perpendicular foot of the point is on the line segment return abs(ux * vy - uy * vx) / sqrt(ux * ux + uy * uy); } } void work(){ cin >> n; cin >> x0 >> y0 >> x >> y; double ans = inf; Point q, z, pp; q.x = x0;q.y = y0; pp.x = x;pp.y = y; for(int i = 1; i <= n; ++i){ cin >> xx >> yy; z.x = xx + q.x; z.y = yy + q.y; double cnt = pointToLine(z, q, pp); if(ans - cnt > eps)ans = cnt; q.x = z.x; q.y = z.y; } printf("%.8lf", ans); } int main(){ io; work(); return 0; }
E-true and false sign in questions
Title Description:
long long f(long long x){ if(x==1)return 1; return f(x/2)+f(x/2+x%2); }
Input x, output f(x)
Idea:
Obviously, f(x) = x, output is enough
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define inf 0x3f3f3f3f #define mod 998244353 #define m_p(a,b) make_pair(a, b) #define mem(a,b) memset((a),(b),sizeof(a)) #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) typedef long long ll; typedef pair <int,int> pii; #define MAX 300000 + 50 int n, m; ll x; void work(){ cin >> x; cout << x << endl; } int main(){ io; work(); return 0; }
Notation of F-xiaohong
Title Description:
Give two ways to express music score. Give one of them and let you express it with the other
The specific meaning of the question will not be repeated
Idea:
Small simulation, you can use a cnt to count, you can also use a prefix and to record low and high tones
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define inf 0x3f3f3f3f #define mod 998244353 #define m_p(a,b) make_pair(a, b) #define mem(a,b) memset((a),(b),sizeof(a)) #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) typedef long long ll; typedef pair <int,int> pii; #define MAX 300000 + 50 int n, m; string s, t; int br[MAX]; map<char, char>mp; void work(){ mp['C'] = '1'; mp['D'] = '2'; mp['E'] = '3'; mp['F'] = '4'; mp['G'] = '5'; mp['A'] = '6'; mp['B'] = '7'; cin >> s; n = (int)s.size(); s = " " + s; for(int i = 1; i <= n; ++i){ br[i] += br[i - 1]; if(s[i] == '<')--br[i]; else if(s[i] == '>')++br[i]; else{ t += mp[s[i]]; if(br[i] > 0){ int num = br[i]; while (num--) { t += '*'; } } else if(br[i] < 0){ int num = -br[i]; while (num--) { t += '.'; } } } } cout << t << endl; } int main(){ work(); return 0; }
G-subsequence weight product
Title Description:
Define the weight of an array as the maximum value multiplied by the minimum value of the array
For an array, ask the product of the weights of all non empty subsequences of the array, module 1e9+7
Idea:
After analyzing the hand model, we can find that we can start from the binary point of view. First, arrange the order from large to small, and set the i-th number as x. if it is the maximum value of a word sequence, the position from 1 to i-1 can not be selected, and the following n-i number is optional, that is, there are 2 n − i 2^{n-i} 2n − i opportunities as the maximum, similarly, there are 2 i − 1 2^{i-1} 2i − 1 chance as the minimum, then the contribution of this number x is x 2 n − i + 2 i − 1 x^{2^{n-i} + 2^{i-1}} x2n − i+2i − 1, and then one Euler power reduction
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define inf 0x3f3f3f3f #define mod 1000000007 #define m_p(a,b) make_pair(a, b) #define mem(a,b) memset((a),(b),sizeof(a)) #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) typedef long long ll; typedef pair <int,int> pii; #define MAX 300000 + 50 int n, m; ll tr[MAX]; ll q_pow(ll a, ll b, ll Mod){ ll ans = 1; while(b > 0){ if(b & 1)ans = ans * a % Mod; a = a * a % Mod; b >>= 1; } return ans; } ll uller(ll a, ll b, ll c){ ll d = q_pow(b, c, mod - 1) + mod - 1; ll cnt = q_pow(a, d, mod); return cnt; } void work(){ cin >> n; for(int i = 1; i <= n; ++i){ cin >> tr[i]; } sort(tr + 1, tr + 1 + n, greater<ll>()); ll ans = 1; for(ll i = 1; i <= n; ++i){ ans = (ans * uller(tr[i], 2, n - i)) % mod; ans = (ans * uller(tr[i], 2, i - 1)) % mod; } cout << ans << endl; } int main(){ io; work(); return 0; }
H-zhenzhen check-in question
Title Description:
Little red and purple are trapped inside a cube. Purple first chose a location, and then Xiao Hong chose a location. Purple hopes to be as close to Xiaohong as possible, and Xiaohong hopes to be as far away from purple as possible. Both will choose the optimal strategy.
Their final distance is known to be x. Xiao Hong wants to know the volume of cube?
Idea:
Obviously, Xiaozi will choose the center of the cube, because if Xiaozi doesn't choose the center, Xiaozi can choose the vertex farthest from Xiaozi. In this way, the distance between the two will be greater than the distance from the center to the vertex, so Xiaozi is in the center and Xiaohong is in the vertex
So just push a formula
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define inf 0x3f3f3f3f #define mod 998244353 #define m_p(a,b) make_pair(a, b) #define mem(a,b) memset((a),(b),sizeof(a)) #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) typedef long long ll; typedef pair <int,int> pii; #define MAX 300000 + 50 int n, m; double x; void work(){ cin >> x; x *= 2; x /= sqrt(3); x = x * x * x; printf("%.6lf\n",x); } int main(){ io; work(); return 0; }
I-exploding runes and cards
Title Description:
n kinds of cards. Each card will consume ai's magic power, which is bi. Select several cards so that the total amount of magic consumed is a multiple of k, and seek the maximum power caused by energy
Idea:
knapsack problem
dp[i][j] represents the maximum power that can be generated when the total magic consumed by the first I cards is% k=j
d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ ( j − a r [ i ] + k ) dp[i][j] = max(dp[i - 1][j], dp[i - 1][(j - ar[i] + k) % k] + br[i]); dp[i][j]=max(dp[i−1][j],dp[i−1][(j−ar[i]+k)
Pay attention to initialization, dp[0][0] = 0, and all others are assigned - inf
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define inf 0x3f3f3f3f #define mod 998244353 #define m_p(a,b) make_pair(a, b) #define mem(a,b) memset((a),(b),sizeof(a)) #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) typedef long long ll; typedef pair <int,int> pii; #define MAX 300000 + 50 int n, m, k; ll ar[1005]; ll br[1005]; ll dp[1005][1005]; void work(){ cin >> n >> k; for(int i = 1; i <= n; ++i){ cin >> ar[i] >> br[i]; ar[i] %= k; } memset(dp, -inf, sizeof(dp)); dp[0][0] = 0; for(int i = 1; i <= n; ++i){ for(int j = 0; j <= k - 1; ++j){ dp[i][j] = max(dp[i - 1][j], dp[i - 1][(j - ar[i] + k) % k] + br[i]); } } if(dp[n][0] == 0)cout << -1 << endl; else cout << dp[n][0] << endl; } int main(){ io; work(); return 0; }
Minimum common multiple of J-interval composite number
Title Description:
The least common multiple of all composite numbers in Q [l, r], module 1e9+7
Idea:
The range is very small, so you can use Euler sieve to screen out all composite numbers in the interval, then decompose them one by one to find out the maximum power of each factor, and finally calculate the answer. The degree of responsibility is O ( n ∗ s q r t ( n ) ) O(n*sqrt(n)) O(n * sqrt(n)), I can't understand the method of problem solving, but its complexity is O ( n l o g n ) O(nlogn) O(nlogn)
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define inf 0x3f3f3f3f #define mod 1000000007 #define m_p(a,b) make_pair(a, b) #define mem(a,b) memset((a),(b),sizeof(a)) #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) typedef long long ll; typedef pair <int,int> pii; #define MAX 300000 + 50 int n, m; int l, r; int tr[MAX]; int tot; bool vis[30050]; int prime[30050];//1e8 has a prime number less than 6e6 map<int, int>mp; void euler_sieve(int n){ for(int i = 2; i <= n; ++i){ if(!vis[i])prime[++tot] = i; for(int j = 1; i * prime[j] <= n && j <= tot; ++j){ vis[prime[j] * i] = 1; if(i % prime[j] == 0)break; } } } void divid(int p){ for(int i = 2; i <= p / i; ++i){ if(p % i == 0){ int num = 0; while (p % i == 0) { ++num; p /= i; } mp[i] = max(mp[i], num); } } if(p > 1)mp[p] = max(mp[p], 1); } ll q_pow(ll a, ll b){ ll ans = 1; while(b > 0){ if(b & 1)ans = ans * a % mod; a = a * a % mod; b >>= 1; } return ans; } void work(){ euler_sieve(30005); cin >> l >> r; bool p = 0; for(int i = l; i <= r; ++i){ if(vis[i]){ p = 1; divid(i); } } if(!p)cout << -1 << endl; else{ ll ans = 1; for(auto [a, b] : mp){ ans *= q_pow(a, b); ans %= mod; } cout << ans << endl; } } int main(){ io; work(); return 0; }
K-xiaohong's true or false sign in question
Title Description:
Idea:
Repeat all the binary bits of x by first calculating how many binary bits x has, and then ( x > > n u n ) + x (x >> nun) + x (x > > nun) + X is an answer
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define inf 0x3f3f3f3f #define mod 998244353 #define m_p(a,b) make_pair(a, b) #define mem(a,b) memset((a),(b),sizeof(a)) #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) typedef long long ll; typedef pair <int,int> pii; #define MAX 300000 + 50 int n, m; int tr[MAX]; ll x; ll getnum(ll x){ int num = 0; while (x) { x /= 2; num ++; } return num; } void work(){ cin >> x; cout << (x << getnum(x)) + x << endl; } int main(){ io; work(); return 0; }